From 67e20e5b4d24454ed6d27a1f383074b2e222d5e3 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 22 Jun 2024 21:06:55 +0900 Subject: [PATCH 001/139] update adapter dependency --- Cargo.lock | 8 ++++---- crates/adapter/Cargo.toml | 2 +- crates/adapter/src/runner/cargo_test.rs | 2 +- crates/adapter/src/runner/jest.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c5f8b6..b402a16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -520,9 +520,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cc86bccfcfd40400582bd0e9a970e0904e0fcfd3890ca935caaa868cf0a787c" +version = "0.0.3" dependencies = [ "anyhow", "clap", @@ -543,6 +541,8 @@ dependencies = [ [[package]] name = "testing-language-server" version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c758bef61755c8ff356a26a92a33b2f9950f2fb90001d5ac0305cc28ab613fba" dependencies = [ "anyhow", "clap", @@ -571,7 +571,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.0.2", + "testing-language-server 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "tree-sitter", "tree-sitter-javascript", "tree-sitter-rust", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 6998179..b8ccf1c 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -testing-language-server = "0.0.2" +testing-language-server = "0.0.3" lsp-types = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 284c889..4d7f611 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -242,7 +242,7 @@ impl Runner for CargoTestRunner { args: testing_language_server::spec::RunFileTestArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; - let workspace_root = args.workspace_root; + let workspace_root = args.workspace; let test_result = std::process::Command::new("cargo") .current_dir(&workspace_root) .arg("test") diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 1bedcb8..1cbc8e0 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -280,7 +280,7 @@ impl Runner for JestRunner { args: testing_language_server::spec::RunFileTestArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; - let workspace_root = args.workspace_root; + let workspace_root = args.workspace; let tempdir = tempdir().unwrap(); let tempdir_path = tempdir.path(); let tempfile_path = tempdir_path.join("jest.json"); From c4a472d5e06b677eb95a36ae52a5c6aa0579002f Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 23 Jun 2024 20:00:36 +0900 Subject: [PATCH 002/139] refresh workspace cache if needed, fix #7 --- src/server.rs | 75 +++++++++++++++++++++++++++++++++++++++------------ src/util.rs | 7 ++++- 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/server.rs b/src/server.rs index 4e8021e..d5ec975 100644 --- a/src/server.rs +++ b/src/server.rs @@ -6,6 +6,7 @@ use crate::spec::DiscoverResult; use crate::spec::RunFileTestResult; use crate::spec::RunFileTestResultItem; use crate::spec::WorkspaceAnalysis; +use crate::util::format_uri; use crate::util::send_stdout; use glob::glob; use glob::Pattern; @@ -70,6 +71,21 @@ impl TestingLS { } } + fn project_dir(&self) -> Result { + let default_project_dir = self + .initialize_params + .clone() + .workspace_folders + .ok_or(LSError::Any(anyhow::anyhow!("No workspace folders found")))?; + let default_workspace_uri = default_project_dir[0].uri.clone(); + let project_dir = self + .options + .project_dir + .clone() + .unwrap_or(default_workspace_uri.to_file_path().unwrap()); + Ok(project_dir) + } + pub fn main_loop(&mut self) -> Result<(), LSError> { loop { let mut size = 0; @@ -133,12 +149,23 @@ impl TestingLS { let uri = params["textDocument"]["uri"] .as_str() .ok_or(serde_json::Error::custom("`textDocument.uri` is not set"))?; + let uri = &format_uri(uri); self.check_file(uri, false)?; } + "textDocument/didOpen" => { + let uri = params["textDocument"]["uri"] + .as_str() + .ok_or(serde_json::Error::custom("`textDocument.uri` is not set"))?; + let uri = &format_uri(uri); + if self.refreshing_needed(uri) { + self.refresh_workspaces_cache()?; + } + } "$/runFileTest" => { let uri = params["uri"] .as_str() .ok_or(serde_json::Error::custom("`uri` is not set"))?; + let uri = &format_uri(uri); self.check_file(uri, false)?; } "$/discoverFileTest" => { @@ -146,6 +173,7 @@ impl TestingLS { let uri = params["uri"] .as_str() .ok_or(serde_json::Error::custom("`uri` is not set"))?; + let uri = &format_uri(uri); let result = self.discover_file(uri)?; send_stdout(&json!({ "jsonrpc": "2.0", @@ -165,19 +193,19 @@ impl TestingLS { fn project_files( base_dir: &Path, - include_pattern: &[String], - exclude_pattern: &[String], + include_patterns: &[String], + exclude_patterns: &[String], ) -> Vec { let mut result: Vec = vec![]; let base_dir = base_dir.to_string_lossy().to_string(); - let exclude_pattern = exclude_pattern + let exclude_pattern = exclude_patterns .iter() .filter_map(|exclude_pattern| { Pattern::new(&format!("!{base_dir}{exclude_pattern}")).ok() }) .collect::>(); - for include_pattern in include_pattern { + for include_pattern in include_patterns { let matched = glob(format!("{base_dir}{include_pattern}").as_str()); if let Ok(entries) = matched { for path in entries.flatten() { @@ -238,17 +266,7 @@ impl TestingLS { pub fn refresh_workspaces_cache(&mut self) -> Result<(), LSError> { let adapter_commands = self.adapter_commands(); - let default_project_dir = self - .initialize_params - .clone() - .workspace_folders - .ok_or(LSError::Any(anyhow::anyhow!("No workspace folders found")))?; - let default_workspace_uri = default_project_dir[0].uri.clone(); - let project_dir = self - .options - .project_dir - .clone() - .unwrap_or(default_workspace_uri.to_file_path().unwrap()); + let project_dir = self.project_dir()?; self.workspaces_cache = vec![]; // Nested and multiple loops, but each count is small for adapter_commands in adapter_commands.values() { @@ -286,6 +304,10 @@ impl TestingLS { .push(WorkspaceAnalysis::new(adapter.clone(), workspace)) } } + eprintln!( + "DEBUGPRINT[2]: server.rs:301: workspaces_cache={:#?}", + self.workspaces_cache + ); send_stdout(&json!({ "jsonrpc": "2.0", "method": "$/detectedWorkspace", @@ -310,8 +332,28 @@ impl TestingLS { Ok(()) } + pub fn refreshing_needed(&self, path: &str) -> bool { + let base_dir = self.project_dir(); + match base_dir { + Ok(base_dir) => self.workspaces_cache.iter().any(|cache| { + let include_patterns = &cache.adapter_config.include_patterns; + let exclude_patterns = &cache.adapter_config.exclude_patterns; + if cache + .workspaces + .iter() + .any(|(_, workspace)| workspace.contains(&path.to_string())) + { + return false; + } + + Self::project_files(&base_dir, include_patterns, exclude_patterns) + .contains(&path.to_owned()) + }), + Err(_) => false, + } + } + pub fn check_file(&mut self, path: &str, refresh_needed: bool) -> Result<(), LSError> { - let path = path.replace("file://", ""); if refresh_needed { self.refresh_workspaces_cache()?; } @@ -459,7 +501,6 @@ impl TestingLS { #[allow(clippy::for_kv_map)] fn discover_file(&self, path: &str) -> Result { - let path = path.replace("file://", ""); let target_paths = vec![path.to_string()]; let mut result: DiscoverResult = vec![]; for WorkspaceAnalysis { diff --git a/src/util.rs b/src/util.rs index ef75770..0787ac9 100644 --- a/src/util.rs +++ b/src/util.rs @@ -10,11 +10,16 @@ pub fn extension_from_url_str(url_str: &str) -> Option { pub fn send_stdout(message: &T) -> Result<(), LSError> where - T: ?Sized + Serialize, + T: ?Sized + Serialize + std::fmt::Debug, { + tracing::info!("send stdout: {:#?}", message); let msg = serde_json::to_string(message)?; let mut stdout = stdout().lock(); write!(stdout, "Content-Length: {}\r\n\r\n{}", msg.len(), msg)?; stdout.flush()?; Ok(()) } + +pub fn format_uri(uri: &str) -> String { + uri.replace("file://", "") +} From 582589af608f144a5b97e9b1c85f9d23144a26af Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 24 Jun 2024 00:34:04 +0900 Subject: [PATCH 003/139] test only the file for file level test --- src/server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.rs b/src/server.rs index 2ec012d..32e2bfe 100644 --- a/src/server.rs +++ b/src/server.rs @@ -363,7 +363,7 @@ impl TestingLS { if !paths.contains(&path.to_string()) { continue; } - let _ = self.check(adapter, workspace, paths); + let _ = self.check(adapter, workspace, &[path.to_string()]); } }, ); From 80ee356a06f0c49be5243ba3486b278913939335 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 30 Jun 2024 18:18:27 +0900 Subject: [PATCH 004/139] add example of go project --- test_proj/go/README.md | 1 + test_proj/go/cases.go | 9 +++++ test_proj/go/cases_test.go | 49 +++++++++++++++++++++++++ test_proj/go/example.go | 7 ++++ test_proj/go/example_test.go | 15 ++++++++ test_proj/go/go.mod | 11 ++++++ test_proj/go/go.sum | 15 ++++++++ test_proj/go/main.go | 15 ++++++++ test_proj/go/main_tagged_test.go | 14 +++++++ test_proj/go/main_test.go | 15 ++++++++ test_proj/go/many_table_test.go | 32 ++++++++++++++++ test_proj/go/map_table_test.go | 40 ++++++++++++++++++++ test_proj/go/suite_test.go | 39 ++++++++++++++++++++ test_proj/go/three_level_nested_test.go | 25 +++++++++++++ 14 files changed, 287 insertions(+) create mode 100644 test_proj/go/README.md create mode 100644 test_proj/go/cases.go create mode 100644 test_proj/go/cases_test.go create mode 100644 test_proj/go/example.go create mode 100644 test_proj/go/example_test.go create mode 100644 test_proj/go/go.mod create mode 100644 test_proj/go/go.sum create mode 100644 test_proj/go/main.go create mode 100644 test_proj/go/main_tagged_test.go create mode 100644 test_proj/go/main_test.go create mode 100644 test_proj/go/many_table_test.go create mode 100644 test_proj/go/map_table_test.go create mode 100644 test_proj/go/suite_test.go create mode 100644 test_proj/go/three_level_nested_test.go diff --git a/test_proj/go/README.md b/test_proj/go/README.md new file mode 100644 index 0000000..5824146 --- /dev/null +++ b/test_proj/go/README.md @@ -0,0 +1 @@ +This directory is from https://github.com/nvim-neotest/neotest-go/tree/main/neotest_go. diff --git a/test_proj/go/cases.go b/test_proj/go/cases.go new file mode 100644 index 0000000..aa5c918 --- /dev/null +++ b/test_proj/go/cases.go @@ -0,0 +1,9 @@ +package main + +func add(a, b int) int { + return a + b +} + +func subtract(a, b int) int { + return a - b +} diff --git a/test_proj/go/cases_test.go b/test_proj/go/cases_test.go new file mode 100644 index 0000000..7c39201 --- /dev/null +++ b/test_proj/go/cases_test.go @@ -0,0 +1,49 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSubtract(t *testing.T) { + testCases := []struct { + desc string + a int + b int + want int + }{ + { + desc: "test one", + a: 1, + b: 2, + want: 3, + }, + { + desc: "test two", + a: 1, + b: 2, + want: 7, + }, + } + for _, tC := range testCases { + t.Run(tC.desc, func(t *testing.T) { + assert.Equal(t, tC.want, subtract(tC.a, tC.b)) + }) + } +} + +func TestAdd(t *testing.T) { + t.Run("test one", func(t *testing.T) { + assert.Equal(t, 3, add(1, 2)) + }) + + t.Run("test two", func(t *testing.T) { + assert.Equal(t, 5, add(1, 2)) + }) + + variable := "string" + t.Run(variable, func(t *testing.T) { + assert.Equal(t, 3, add(1, 2)) + }) +} diff --git a/test_proj/go/example.go b/test_proj/go/example.go new file mode 100644 index 0000000..a1f73ad --- /dev/null +++ b/test_proj/go/example.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func hello() { + fmt.Println("hello world") +} diff --git a/test_proj/go/example_test.go b/test_proj/go/example_test.go new file mode 100644 index 0000000..34ba0b0 --- /dev/null +++ b/test_proj/go/example_test.go @@ -0,0 +1,15 @@ +package main + +func Example_hello_ok() { + hello() + + // Output: + // hello world +} + +func Example_hello_ng() { + hello() + + // Output: + // NG pattern +} diff --git a/test_proj/go/go.mod b/test_proj/go/go.mod new file mode 100644 index 0000000..7e92512 --- /dev/null +++ b/test_proj/go/go.mod @@ -0,0 +1,11 @@ +module neotest_go + +go 1.18 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.4.0 // indirect + github.com/stretchr/testify v1.7.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/test_proj/go/go.sum b/test_proj/go/go.sum new file mode 100644 index 0000000..feea66e --- /dev/null +++ b/test_proj/go/go.sum @@ -0,0 +1,15 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/test_proj/go/main.go b/test_proj/go/main.go new file mode 100644 index 0000000..880c6bf --- /dev/null +++ b/test_proj/go/main.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + fmt.Println("hello world") +} + +func addOne(x int) int { + return x + 1 +} + +func addTwo(x int) int { + return x + 2 +} diff --git a/test_proj/go/main_tagged_test.go b/test_proj/go/main_tagged_test.go new file mode 100644 index 0000000..6269007 --- /dev/null +++ b/test_proj/go/main_tagged_test.go @@ -0,0 +1,14 @@ +//go:build files +// +build files + +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddOne2(t *testing.T) { + assert.Equal(t, 2, addOne(1)) +} diff --git a/test_proj/go/main_test.go b/test_proj/go/main_test.go new file mode 100644 index 0000000..9b7c642 --- /dev/null +++ b/test_proj/go/main_test.go @@ -0,0 +1,15 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddOne(t *testing.T) { + assert.Equal(t, 2, addOne(1)) +} + +func TestAddTwo(t *testing.T) { + assert.Equal(t, 3, addTwo(1)) +} diff --git a/test_proj/go/many_table_test.go b/test_proj/go/many_table_test.go new file mode 100644 index 0000000..3ee7c8c --- /dev/null +++ b/test_proj/go/many_table_test.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "net/http" + "testing" +) + +func TestSomeTest(t *testing.T) { + tt := []struct { + name string + method string + url string + apiKey string + status int + }{ + {name: "AccessDenied1", method: http.MethodGet, url: "/api/nothing", apiKey: "lalala", status: http.StatusForbidden}, + {name: "AccessDenied2", method: http.MethodGet, url: "/api/nothing", apiKey: "lalala", status: http.StatusForbidden}, + {name: "AccessDenied3", method: http.MethodGet, url: "/api/nothing", apiKey: "lalala", status: http.StatusForbidden}, + {name: "AccessDenied4", method: http.MethodGet, url: "/api/nothing", apiKey: "lalala", status: http.StatusForbidden}, + {name: "AccessDenied5", method: http.MethodGet, url: "/api/nothing", apiKey: "lalala", status: http.StatusForbidden}, + {name: "AccessDenied6", method: http.MethodGet, url: "/api/nothing", apiKey: "lalala", status: http.StatusForbidden}, + } + + for _, tc := range tt { + tc := tc + t.Run(tc.name, func(_ *testing.T) { + fmt.Println(tc.name, tc.method, tc.url, tc.apiKey, tc.status) + }) + } + +} diff --git a/test_proj/go/map_table_test.go b/test_proj/go/map_table_test.go new file mode 100644 index 0000000..2fcba40 --- /dev/null +++ b/test_proj/go/map_table_test.go @@ -0,0 +1,40 @@ +package main + +import ( + "reflect" + "strings" + "testing" +) + +func TestSplit(t *testing.T) { + tests := map[string]struct { + input string + sep string + want []string + }{ + "simple": {input: "a/b/c", sep: "/", want: []string{"a", "b", "c"}}, + "wrong sep": {input: "a/b/c", sep: ",", want: []string{"a/b/c"}}, + "no sep": {input: "abc", sep: "/", want: []string{"abc"}}, + "trailing sep": {input: "a/b/c/", sep: "/", want: []string{"a", "b", "c"}}, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + got := Split(tc.input, tc.sep) + if !reflect.DeepEqual(tc.want, got) { + t.Fatalf("%s: expected: %v, got: %v", name, tc.want, got) + } + }) + } +} + +func Split(s, sep string) []string { + var result []string + i := strings.Index(s, sep) + for i > -1 { + result = append(result, s[:i]) + s = s[i+len(sep):] + i = strings.Index(s, sep) + } + return append(result, s) +} diff --git a/test_proj/go/suite_test.go b/test_proj/go/suite_test.go new file mode 100644 index 0000000..151fb00 --- /dev/null +++ b/test_proj/go/suite_test.go @@ -0,0 +1,39 @@ +package main + +// Basic imports +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +// Define the suite, and absorb the built-in basic suite +// functionality from testify - including a T() method which +// returns the current testing context +type ExampleTestSuite struct { + suite.Suite + VariableThatShouldStartAtFive int +} + +// Make sure that VariableThatShouldStartAtFive is set to five +// before each test +func (suite *ExampleTestSuite) SetupTest() { + suite.VariableThatShouldStartAtFive = 5 +} + +// All methods that begin with "Test" are run as tests within a +// suite. +func (suite *ExampleTestSuite) TestExample() { + assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) +} + +func (suite *ExampleTestSuite) TestExampleFailure() { + assert.Equal(suite.T(), 5, 3) +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestExampleTestSuite(t *testing.T) { + suite.Run(t, new(ExampleTestSuite)) +} diff --git a/test_proj/go/three_level_nested_test.go b/test_proj/go/three_level_nested_test.go new file mode 100644 index 0000000..9d3a2f9 --- /dev/null +++ b/test_proj/go/three_level_nested_test.go @@ -0,0 +1,25 @@ +package main + +import "testing" + +func TestOdd(t *testing.T) { + t.Run("odd", func(t *testing.T) { + t.Run("5 is odd", func(t *testing.T) { + if 5%2 != 1 { + t.Error("5 is actually odd") + } + t.Run("9 is odd", func(t *testing.T) { + if 9%2 != 1 { + t.Error("5 is actually odd") + } + }) + }) + t.Run("7 is odd", func(t *testing.T) { + if 7%2 != 1 { + t.Error("7 is actually odd") + } + }) + + }) + +} From 07b516e79811626d21b12f877cf06ac3c9645608 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 30 Jun 2024 18:20:27 +0900 Subject: [PATCH 005/139] add `go test` feature to adapter --- Cargo.lock | 15 ++ crates/adapter/Cargo.toml | 5 + crates/adapter/src/log.rs | 14 ++ crates/adapter/src/main.rs | 19 +- crates/adapter/src/model.rs | 14 +- crates/adapter/src/runner/go.rs | 383 ++++++++++++++++++++++++++++++ crates/adapter/src/runner/mod.rs | 2 + crates/adapter/src/runner/util.rs | 50 ++++ crates/adapter/tests/go-test.txt | 161 +++++++++++++ 9 files changed, 649 insertions(+), 14 deletions(-) create mode 100644 crates/adapter/src/log.rs create mode 100644 crates/adapter/src/runner/go.rs create mode 100644 crates/adapter/src/runner/util.rs create mode 100644 crates/adapter/tests/go-test.txt diff --git a/Cargo.lock b/Cargo.lock index b402a16..3bbce75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -566,13 +566,18 @@ version = "0.0.1" dependencies = [ "anyhow", "clap", + "dirs", "lsp-types", "regex", "serde", "serde_json", "tempfile", "testing-language-server 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing", + "tracing-appender", + "tracing-subscriber", "tree-sitter", + "tree-sitter-go", "tree-sitter-javascript", "tree-sitter-rust", ] @@ -717,6 +722,16 @@ dependencies = [ "regex", ] +[[package]] +name = "tree-sitter-go" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb318be5ccf75f44e054acf6898a5c95d59b53443eed578e16be0cd7ec037f" +dependencies = [ + "cc", + "tree-sitter", +] + [[package]] name = "tree-sitter-javascript" version = "0.21.0" diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index b8ccf1c..8b74dcc 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -19,3 +19,8 @@ tree-sitter-rust = "0.21.2" anyhow = { workspace = true } tempfile = "3.10.1" tree-sitter-javascript = "0.21.0" +tree-sitter-go = "0.21.0" +tracing-appender = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, default-features = false } +dirs = "5.0.1" diff --git a/crates/adapter/src/log.rs b/crates/adapter/src/log.rs new file mode 100644 index 0000000..c409633 --- /dev/null +++ b/crates/adapter/src/log.rs @@ -0,0 +1,14 @@ +use tracing_appender::non_blocking::WorkerGuard; + +pub struct Log; + +impl Log { + pub fn init() -> Result { + let home_dir = dirs::home_dir().unwrap(); + let log_path = home_dir.join(".config/testing_ls_adapter/logs"); + let file_appender = tracing_appender::rolling::daily(log_path, "prefix.log"); + let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); + tracing_subscriber::fmt().with_writer(non_blocking).init(); + Ok(guard) + } +} diff --git a/crates/adapter/src/main.rs b/crates/adapter/src/main.rs index 870b560..0638223 100644 --- a/crates/adapter/src/main.rs +++ b/crates/adapter/src/main.rs @@ -1,6 +1,8 @@ use crate::model::AvailableTestKind; use crate::model::Runner; +use anyhow::anyhow; use clap::Parser; +use log::Log; use std::io; use std::io::Write; use std::str::FromStr; @@ -9,18 +11,18 @@ use testing_language_server::spec::AdapterCommands; use testing_language_server::spec::DetectWorkspaceArgs; use testing_language_server::spec::DiscoverArgs; use testing_language_server::spec::RunFileTestArgs; +pub mod log; pub mod model; pub mod runner; fn pick_test_from_extra( extra: &mut [String], ) -> Result<(Vec, AvailableTestKind), anyhow::Error> { - // extraから--test-kind=のものを取り出し、元の配列から`--test-kind=`のものは除外する let mut extra = extra.to_vec(); let index = extra .iter() .position(|arg| arg.starts_with("--test-kind=")) - .unwrap(); + .ok_or(anyhow!("test-kind is not found"))?; let test_kind = extra.remove(index); let language = test_kind.replace("--test-kind=", ""); @@ -41,13 +43,14 @@ fn handle(commands: AdapterCommands) -> Result<(), LSError> { } AdapterCommands::DetectWorkspace(mut commands) => { let (extra, test_kind) = pick_test_from_extra(&mut commands.extra)?; - test_kind.detect_workspaces_root(DetectWorkspaceArgs { extra, ..commands })?; + test_kind.detect_workspaces(DetectWorkspaceArgs { extra, ..commands })?; Ok(()) } } } fn main() { + let _guard = Log::init().expect("Failed to initialize logger"); let args = AdapterCommands::parse(); if let Err(error) = handle(args) { io::stderr() @@ -60,10 +63,8 @@ fn main() { mod tests { use super::*; use crate::runner::cargo_test::CargoTestRunner; - use crate::runner::jest::JestRunner; #[test] - // If `--test-kind=` is not present, then return Err fn error_test_kind_detection() { let mut extra = vec![]; pick_test_from_extra(&mut extra).unwrap_err(); @@ -72,22 +73,20 @@ mod tests { } #[test] - // If `--test-kind=` is present, then return Ok(value) - fn test_kind_detection() { + fn single_test_kind_detection() { let mut extra = vec!["--test-kind=cargo-test".to_string()]; let (_, language) = pick_test_from_extra(&mut extra).unwrap(); assert_eq!(language, AvailableTestKind::CargoTest(CargoTestRunner)); } #[test] - // If multiple `--test-kind=` are present, then return first one - fn error_multiple_test_kind_detection() { + fn multiple_test_kind_results_first_kind() { let mut extra = vec![ "--test-kind=cargo-test".to_string(), "--test-kind=jest".to_string(), "--test-kind=foo".to_string(), ]; let (_, test_kind) = pick_test_from_extra(&mut extra).unwrap(); - assert_eq!(test_kind, AvailableTestKind::Jest(JestRunner)); + assert_eq!(test_kind, AvailableTestKind::CargoTest(CargoTestRunner)); } } diff --git a/crates/adapter/src/model.rs b/crates/adapter/src/model.rs index 7c3a007..7302cd9 100644 --- a/crates/adapter/src/model.rs +++ b/crates/adapter/src/model.rs @@ -1,4 +1,5 @@ use crate::runner::cargo_test::CargoTestRunner; +use crate::runner::go::GoTestRunner; use std::str::FromStr; use testing_language_server::error::LSError; use testing_language_server::spec::DetectWorkspaceArgs; @@ -11,12 +12,14 @@ use crate::runner::jest::JestRunner; pub enum AvailableTestKind { CargoTest(CargoTestRunner), Jest(JestRunner), + GoTest(GoTestRunner), } impl Runner for AvailableTestKind { fn disover(&self, args: DiscoverArgs) -> Result<(), LSError> { match self { AvailableTestKind::CargoTest(runner) => runner.disover(args), AvailableTestKind::Jest(runner) => runner.disover(args), + AvailableTestKind::GoTest(runner) => runner.disover(args), } } @@ -24,13 +27,15 @@ impl Runner for AvailableTestKind { match self { AvailableTestKind::CargoTest(runner) => runner.run_file_test(args), AvailableTestKind::Jest(runner) => runner.run_file_test(args), + AvailableTestKind::GoTest(runner) => runner.run_file_test(args), } } - fn detect_workspaces_root(&self, args: DetectWorkspaceArgs) -> Result<(), LSError> { + fn detect_workspaces(&self, args: DetectWorkspaceArgs) -> Result<(), LSError> { match self { - AvailableTestKind::CargoTest(runner) => runner.detect_workspaces_root(args), - AvailableTestKind::Jest(runner) => runner.detect_workspaces_root(args), + AvailableTestKind::CargoTest(runner) => runner.detect_workspaces(args), + AvailableTestKind::Jest(runner) => runner.detect_workspaces(args), + AvailableTestKind::GoTest(runner) => runner.detect_workspaces(args), } } } @@ -42,6 +47,7 @@ impl FromStr for AvailableTestKind { match s { "cargo-test" => Ok(AvailableTestKind::CargoTest(CargoTestRunner)), "jest" => Ok(AvailableTestKind::Jest(JestRunner)), + "go-test" => Ok(AvailableTestKind::GoTest(GoTestRunner)), _ => Err(anyhow::anyhow!("Unknown test kind: {}", s)), } } @@ -50,5 +56,5 @@ impl FromStr for AvailableTestKind { pub trait Runner { fn disover(&self, args: DiscoverArgs) -> Result<(), LSError>; fn run_file_test(&self, args: RunFileTestArgs) -> Result<(), LSError>; - fn detect_workspaces_root(&self, args: DetectWorkspaceArgs) -> Result<(), LSError>; + fn detect_workspaces(&self, args: DetectWorkspaceArgs) -> Result<(), LSError>; } diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs new file mode 100644 index 0000000..f743f77 --- /dev/null +++ b/crates/adapter/src/runner/go.rs @@ -0,0 +1,383 @@ +use crate::model::Runner; +use anyhow::anyhow; +use lsp_types::Diagnostic; +use lsp_types::Position; +use lsp_types::Range; +use regex::Regex; +use serde::Deserialize; +use std::collections::HashMap; +use std::path::PathBuf; +use std::process::Output; +use std::str::FromStr; +use testing_language_server::error::LSError; +use testing_language_server::spec::DiscoverResult; +use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::RunFileTestResult; +use testing_language_server::spec::RunFileTestResultItem; +use testing_language_server::spec::TestItem; +use tree_sitter::Point; +use tree_sitter::Query; +use tree_sitter::QueryCursor; + +use super::util::detect_workspaces_from_file_paths; + +// If the character value is greater than the line length it defaults back to the line length. +const MAX_CHAR_LENGTH: u32 = 10000; + +#[derive(Deserialize, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] +enum Action { + Start, + Run, + Output, + Fail, + Pass, +} + +#[allow(dead_code)] +#[derive(Deserialize)] +#[serde(rename_all = "PascalCase")] +struct TestResultLine { + time: String, + action: Action, + package: String, + test: Option, + output: Option, +} + +fn get_position_from_output(output: &str) -> Option<(String, u32)> { + let pattern = r"^\s{4}(.*_test\.go):(\d+):"; + let re = Regex::new(pattern).unwrap(); + if let Some(captures) = re.captures(output) { + if let (Some(file_name), Some(lnum)) = (captures.get(1), captures.get(2)) { + return Some(( + file_name.as_str().to_string(), + lnum.as_str().parse::().unwrap() - 1, + )); + } + } + None +} +fn get_log_from_output(output: &str) -> String { + output.replace(" ", "") +} + +fn parse_diagnostics( + contents: &str, + workspace_root: PathBuf, + file_paths: &[String], +) -> Result { + let contents = contents.replace("\r\n", "\n"); + let lines = contents.lines(); + let mut result_map: HashMap> = HashMap::new(); + let mut file_name: Option = None; + let mut lnum: Option = None; + let mut message = String::new(); + let mut last_action: Option = None; + for line in lines { + let value: TestResultLine = serde_json::from_str(line).map_err(|e| anyhow!("{:?}", e))?; + match value.action { + Action::Run => { + file_name = None; + message = String::new(); + } + Action::Output => { + let output = &value.output.unwrap(); + if let Some((detected_file_name, detected_lnum)) = get_position_from_output(output) + { + file_name = Some(detected_file_name); + lnum = Some(detected_lnum); + message = String::new(); + } else { + message += &get_log_from_output(output); + } + } + _ => {} + } + let current_action = value.action; + let is_action_changed = last_action.as_ref() != Some(¤t_action); + if is_action_changed { + last_action = Some(current_action); + } else { + continue; + } + + if let (Some(detected_fn), Some(detected_lnum)) = (&file_name, lnum) { + let diagnostic = Diagnostic { + range: Range { + start: Position { + line: detected_lnum, + character: 1, + }, + end: Position { + line: detected_lnum, + character: MAX_CHAR_LENGTH, + }, + }, + message: message.clone(), + ..Diagnostic::default() + }; + let file_path = workspace_root + .join(detected_fn) + .to_str() + .unwrap() + .to_owned(); + if file_paths.contains(&file_path) { + result_map.entry(file_path).or_default().push(diagnostic); + } + file_name = None; + lnum = None; + } + } + + Ok(result_map + .into_iter() + .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) + .collect()) +} + +fn discover(file_path: &str) -> Result, LSError> { + let mut parser = tree_sitter::Parser::new(); + let mut test_items: Vec = vec![]; + parser + .set_language(&tree_sitter_go::language()) + .expect("Error loading Rust grammar"); + let source_code = std::fs::read_to_string(file_path)?; + let tree = parser.parse(&source_code, None).unwrap(); + let query_string = r#" + ;;query + ((function_declaration + name: (identifier) @test.name) + (#match? @test.name "^(Test|Example)")) + @test.definition + + (method_declaration + name: (field_identifier) @test.name + (#match? @test.name "^(Test|Example)")) @test.definition + + (call_expression + function: (selector_expression + field: (field_identifier) @test.method) + (#match? @test.method "^Run$") + arguments: (argument_list . (interpreted_string_literal) @test.name)) + @test.definition +;; query for list table tests + (block + (short_var_declaration + left: (expression_list + (identifier) @test.cases) + right: (expression_list + (composite_literal + (literal_value + (literal_element + (literal_value + (keyed_element + (literal_element + (identifier) @test.field.name) + (literal_element + (interpreted_string_literal) @test.name)))) @test.definition)))) + (for_statement + (range_clause + left: (expression_list + (identifier) @test.case) + right: (identifier) @test.cases1 + (#eq? @test.cases @test.cases1)) + body: (block + (expression_statement + (call_expression + function: (selector_expression + field: (field_identifier) @test.method) + (#match? @test.method "^Run$") + arguments: (argument_list + (selector_expression + operand: (identifier) @test.case1 + (#eq? @test.case @test.case1) + field: (field_identifier) @test.field.name1 + (#eq? @test.field.name @test.field.name1)))))))) + +;; query for map table tests + (block + (short_var_declaration + left: (expression_list + (identifier) @test.cases) + right: (expression_list + (composite_literal + (literal_value + (keyed_element + (literal_element + (interpreted_string_literal) @test.name) + (literal_element + (literal_value) @test.definition)))))) + (for_statement + (range_clause + left: (expression_list + ((identifier) @test.key.name) + ((identifier) @test.case)) + right: (identifier) @test.cases1 + (#eq? @test.cases @test.cases1)) + body: (block + (expression_statement + (call_expression + function: (selector_expression + field: (field_identifier) @test.method) + (#match? @test.method "^Run$") + arguments: (argument_list + ((identifier) @test.key.name1 + (#eq? @test.key.name @test.key.name1)))))))) +"#; + let query = + Query::new(&tree_sitter_go::language(), query_string).expect("Error creating query"); + + let mut cursor = QueryCursor::new(); + cursor.set_byte_range(tree.root_node().byte_range()); + let source = source_code.as_bytes(); + let matches = cursor.matches(&query, tree.root_node(), source); + for m in matches { + let mut namespace_name = ""; + let mut test_start_position = Point::default(); + let mut test_end_position = Point::default(); + for capture in m.captures { + let capture_name = query.capture_names()[capture.index as usize]; + let value = capture.node.utf8_text(source)?; + let start_position = capture.node.start_position(); + let end_position = capture.node.end_position(); + match capture_name { + "namespace.name" => { + namespace_name = value; + } + "test.definition" => { + test_start_position = start_position; + test_end_position = end_position; + } + "test.name" => { + let test_name = value; + let test_item = TestItem { + id: format!("{}:{}", namespace_name, test_name), + name: test_name.to_string(), + start_position: Range { + start: Position { + line: test_start_position.row as u32, + character: test_start_position.column as u32, + }, + end: Position { + line: test_start_position.row as u32, + character: MAX_CHAR_LENGTH, + }, + }, + end_position: Range { + start: Position { + line: test_end_position.row as u32, + character: 0, + }, + end: Position { + line: test_end_position.row as u32, + character: test_end_position.column as u32, + }, + }, + }; + test_items.push(test_item); + test_start_position = Point::default(); + test_end_position = Point::default(); + } + _ => {} + } + } + } + + Ok(test_items) +} + +#[derive(Eq, PartialEq, Hash, Debug)] +pub struct GoTestRunner; +impl Runner for GoTestRunner { + fn disover( + &self, + args: testing_language_server::spec::DiscoverArgs, + ) -> Result<(), testing_language_server::error::LSError> { + let file_paths = args.file_paths; + let mut discover_results: DiscoverResult = vec![]; + + for file_path in file_paths { + let tests = discover(&file_path)?; + discover_results.push(DiscoverResultItem { + tests, + path: file_path, + }); + } + serde_json::to_writer(std::io::stdout(), &discover_results)?; + Ok(()) + } + + fn run_file_test( + &self, + args: testing_language_server::spec::RunFileTestArgs, + ) -> Result<(), testing_language_server::error::LSError> { + let file_paths = args.file_paths; + let default_args = ["-v", "-json", "", "-count=1", "-timeout=60s"]; + let workspace = args.workspace; + let test_result = std::process::Command::new("go") + .current_dir(&workspace) + .arg("test") + .args(default_args) + .args(args.extra) + .output() + .unwrap(); + let Output { stdout, stderr, .. } = test_result; + if stdout.is_empty() && !stderr.is_empty() { + return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); + } + let test_result = String::from_utf8(stdout)?; + let diagnostics: RunFileTestResult = parse_diagnostics( + &test_result, + PathBuf::from_str(&workspace).unwrap(), + &file_paths, + )?; + serde_json::to_writer(std::io::stdout(), &diagnostics)?; + Ok(()) + } + + fn detect_workspaces( + &self, + args: testing_language_server::spec::DetectWorkspaceArgs, + ) -> Result<(), testing_language_server::error::LSError> { + serde_json::to_writer( + std::io::stdout(), + &detect_workspaces_from_file_paths(&args.file_paths, &["go.mod".to_string()]), + )?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::runner::go::discover; + use std::str::FromStr; + use std::{fs::read_to_string, path::PathBuf}; + + use crate::runner::go::parse_diagnostics; + + #[test] + fn test_parse_diagnostics() { + let current_dir = std::env::current_dir().unwrap(); + let test_file_path = current_dir.join("tests/go-test.txt"); + let contents = read_to_string(test_file_path).unwrap(); + let workspace = PathBuf::from_str("/home/demo/test/go/src/test").unwrap(); + let target_file_path = "/home/demo/test/go/src/test/cases_test.go"; + let result = + parse_diagnostics(&contents, workspace, &[target_file_path.to_string()]).unwrap(); + let result = result.first().unwrap(); + assert_eq!(result.path, target_file_path); + let diagnostic = result.diagnostics.first().unwrap(); + assert_eq!(diagnostic.range.start.line, 30); + assert_eq!(diagnostic.range.start.character, 1); + assert_eq!(diagnostic.range.end.line, 30); + assert_eq!(diagnostic.message, "\tError Trace:\tcases_test.go:31\n\tError: \tNot equal: \n\t \texpected: 7\n\t \tactual : -1\n\tTest: \tTestSubtract/test_two\n--- FAIL: TestSubtract (0.00s)\n --- FAIL: TestSubtract/test_one (0.00s)\n"); + } + + #[test] + fn test_discover() { + let file_path = "../../test_proj/go/cases_test.go"; + let test_items = discover(file_path).unwrap(); + assert!(!test_items.is_empty()); + } +} diff --git a/crates/adapter/src/runner/mod.rs b/crates/adapter/src/runner/mod.rs index b534f79..d739aa2 100644 --- a/crates/adapter/src/runner/mod.rs +++ b/crates/adapter/src/runner/mod.rs @@ -1,2 +1,4 @@ pub mod cargo_test; +pub mod go; pub mod jest; +pub mod util; diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs new file mode 100644 index 0000000..863decc --- /dev/null +++ b/crates/adapter/src/runner/util.rs @@ -0,0 +1,50 @@ +use std::collections::HashMap; +use std::path::PathBuf; +use std::str::FromStr; + +/// determine if a particular file is the root of workspace based on whether it is in the same directory +pub fn detect_workspace_from_file(file_path: PathBuf, file_names: &[String]) -> Option { + let parent = file_path.parent(); + if let Some(parent) = parent { + if file_names + .iter() + .any(|file_name| parent.join(file_name).exists()) + { + return Some(parent.to_string_lossy().to_string()); + } else { + detect_workspace_from_file(parent.to_path_buf(), file_names) + } + } else { + None + } +} + +pub fn detect_workspaces_from_file_paths( + target_file_paths: &[String], + file_names: &[String], +) -> HashMap> { + let mut result_map: HashMap> = HashMap::new(); + let mut file_paths = target_file_paths.to_vec(); + file_paths.sort_by_key(|b| std::cmp::Reverse(b.len())); + for file_path in file_paths { + let existing_workspace = result_map + .iter() + .find(|(workspace_root, _)| file_path.contains(workspace_root.as_str())); + if let Some((workspace_root, _)) = existing_workspace { + result_map + .entry(workspace_root.to_string()) + .or_default() + .push(file_path.clone()); + } else { + let workspace = + detect_workspace_from_file(PathBuf::from_str(&file_path).unwrap(), file_names); + if let Some(workspace) = workspace { + result_map + .entry(workspace) + .or_default() + .push(file_path.clone()); + } + } + } + result_map +} diff --git a/crates/adapter/tests/go-test.txt b/crates/adapter/tests/go-test.txt new file mode 100644 index 0000000..064b54b --- /dev/null +++ b/crates/adapter/tests/go-test.txt @@ -0,0 +1,161 @@ +{"Time":"2024-05-25T17:06:16.98464582+09:00","Action":"start","Package":"neotest_go"} +{"Time":"2024-05-25T17:06:16.986822201+09:00","Action":"run","Package":"neotest_go","Test":"TestSubtract"} +{"Time":"2024-05-25T17:06:16.986838849+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract","Output":"=== RUN TestSubtract\n"} +{"Time":"2024-05-25T17:06:16.986859373+09:00","Action":"run","Package":"neotest_go","Test":"TestSubtract/test_one"} +{"Time":"2024-05-25T17:06:16.98686856+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_one","Output":" \tError Trace:\tcases_test.go:31\n"} +{"Time":"2024-05-25T17:06:16.986871386+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_one","Output":" \tError: \tNot equal: \n"} +{"Time":"2024-05-25T17:06:16.986874139+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_one","Output":" \t \texpected: 3\n"} +{"Time":"2024-05-25T17:06:16.986876748+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_one","Output":" \t \tactual : -1\n"} +{"Time":"2024-05-25T17:06:16.986879547+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_one","Output":" \tTest: \tTestSubtract/test_one\n"} +{"Time":"2024-05-25T17:06:16.986883029+09:00","Action":"run","Package":"neotest_go","Test":"TestSubtract/test_two"} +{"Time":"2024-05-25T17:06:16.986885264+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_two","Output":"=== RUN TestSubtract/test_two\n"} +{"Time":"2024-05-25T17:06:16.986888429+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_two","Output":" cases_test.go:31: \n"} +{"Time":"2024-05-25T17:06:16.986891613+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_two","Output":" \tError Trace:\tcases_test.go:31\n"} +{"Time":"2024-05-25T17:06:16.986894222+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_two","Output":" \tError: \tNot equal: \n"} +{"Time":"2024-05-25T17:06:16.986896835+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_two","Output":" \t \texpected: 7\n"} +{"Time":"2024-05-25T17:06:16.986899333+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_two","Output":" \t \tactual : -1\n"} +{"Time":"2024-05-25T17:06:16.986901904+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_two","Output":" \tTest: \tTestSubtract/test_two\n"} +{"Time":"2024-05-25T17:06:16.986906401+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract","Output":"--- FAIL: TestSubtract (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.986910144+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_one","Output":" --- FAIL: TestSubtract/test_one (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.986913275+09:00","Action":"fail","Package":"neotest_go","Test":"TestSubtract/test_one","Elapsed":0} +{"Time":"2024-05-25T17:06:16.986916945+09:00","Action":"output","Package":"neotest_go","Test":"TestSubtract/test_two","Output":" --- FAIL: TestSubtract/test_two (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.986919709+09:00","Action":"fail","Package":"neotest_go","Test":"TestSubtract/test_two","Elapsed":0} +{"Time":"2024-05-25T17:06:16.986922033+09:00","Action":"fail","Package":"neotest_go","Test":"TestSubtract","Elapsed":0} +{"Time":"2024-05-25T17:06:16.986924322+09:00","Action":"run","Package":"neotest_go","Test":"TestAdd"} +{"Time":"2024-05-25T17:06:16.986926439+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd","Output":"=== RUN TestAdd\n"} +{"Time":"2024-05-25T17:06:16.986929637+09:00","Action":"run","Package":"neotest_go","Test":"TestAdd/test_one"} +{"Time":"2024-05-25T17:06:16.986931891+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_one","Output":"=== RUN TestAdd/test_one\n"} +{"Time":"2024-05-25T17:06:16.98693449+09:00","Action":"run","Package":"neotest_go","Test":"TestAdd/test_two"} +{"Time":"2024-05-25T17:06:16.986936644+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_two","Output":"=== RUN TestAdd/test_two\n"} +{"Time":"2024-05-25T17:06:16.986939093+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_two","Output":" cases_test.go:42: \n"} +{"Time":"2024-05-25T17:06:16.986941721+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_two","Output":" \tError Trace:\tcases_test.go:42\n"} +{"Time":"2024-05-25T17:06:16.986944261+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_two","Output":" \tError: \tNot equal: \n"} +{"Time":"2024-05-25T17:06:16.986946773+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_two","Output":" \t \texpected: 5\n"} +{"Time":"2024-05-25T17:06:16.986949247+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_two","Output":" \t \tactual : 3\n"} +{"Time":"2024-05-25T17:06:16.986951706+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_two","Output":" \tTest: \tTestAdd/test_two\n"} +{"Time":"2024-05-25T17:06:16.986954288+09:00","Action":"run","Package":"neotest_go","Test":"TestAdd/string"} +{"Time":"2024-05-25T17:06:16.986956496+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/string","Output":"=== RUN TestAdd/string\n"} +{"Time":"2024-05-25T17:06:16.986959568+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd","Output":"--- FAIL: TestAdd (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.986964387+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_one","Output":" --- PASS: TestAdd/test_one (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.986967557+09:00","Action":"pass","Package":"neotest_go","Test":"TestAdd/test_one","Elapsed":0} +{"Time":"2024-05-25T17:06:16.986970137+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/test_two","Output":" --- FAIL: TestAdd/test_two (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.986973398+09:00","Action":"fail","Package":"neotest_go","Test":"TestAdd/test_two","Elapsed":0} +{"Time":"2024-05-25T17:06:16.986976554+09:00","Action":"output","Package":"neotest_go","Test":"TestAdd/string","Output":" --- PASS: TestAdd/string (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.986979769+09:00","Action":"pass","Package":"neotest_go","Test":"TestAdd/string","Elapsed":0} +{"Time":"2024-05-25T17:06:16.98698262+09:00","Action":"fail","Package":"neotest_go","Test":"TestAdd","Elapsed":0} +{"Time":"2024-05-25T17:06:16.98698541+09:00","Action":"run","Package":"neotest_go","Test":"TestAddOne"} +{"Time":"2024-05-25T17:06:16.986987976+09:00","Action":"output","Package":"neotest_go","Test":"TestAddOne","Output":"=== RUN TestAddOne\n"} +{"Time":"2024-05-25T17:06:16.986990912+09:00","Action":"output","Package":"neotest_go","Test":"TestAddOne","Output":"--- PASS: TestAddOne (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.986994224+09:00","Action":"pass","Package":"neotest_go","Test":"TestAddOne","Elapsed":0} +{"Time":"2024-05-25T17:06:16.986996509+09:00","Action":"run","Package":"neotest_go","Test":"TestAddTwo"} +{"Time":"2024-05-25T17:06:16.986999108+09:00","Action":"output","Package":"neotest_go","Test":"TestAddTwo","Output":"=== RUN TestAddTwo\n"} +{"Time":"2024-05-25T17:06:16.98700243+09:00","Action":"output","Package":"neotest_go","Test":"TestAddTwo","Output":"--- PASS: TestAddTwo (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987005287+09:00","Action":"pass","Package":"neotest_go","Test":"TestAddTwo","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987008349+09:00","Action":"run","Package":"neotest_go","Test":"TestSomeTest"} +{"Time":"2024-05-25T17:06:16.987011032+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest","Output":"=== RUN TestSomeTest\n"} +{"Time":"2024-05-25T17:06:16.987014678+09:00","Action":"run","Package":"neotest_go","Test":"TestSomeTest/AccessDenied1"} +{"Time":"2024-05-25T17:06:16.987017664+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied1","Output":"=== RUN TestSomeTest/AccessDenied1\n"} +{"Time":"2024-05-25T17:06:16.98702332+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied1","Output":"AccessDenied1 GET /api/nothing lalala 403\n"} +{"Time":"2024-05-25T17:06:16.987030097+09:00","Action":"run","Package":"neotest_go","Test":"TestSomeTest/AccessDenied2"} +{"Time":"2024-05-25T17:06:16.9870326+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied2","Output":"=== RUN TestSomeTest/AccessDenied2\n"} +{"Time":"2024-05-25T17:06:16.987035243+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied2","Output":"AccessDenied2 GET /api/nothing lalala 403\n"} +{"Time":"2024-05-25T17:06:16.98703803+09:00","Action":"run","Package":"neotest_go","Test":"TestSomeTest/AccessDenied3"} +{"Time":"2024-05-25T17:06:16.987040299+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied3","Output":"=== RUN TestSomeTest/AccessDenied3\n"} +{"Time":"2024-05-25T17:06:16.987042979+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied3","Output":"AccessDenied3 GET /api/nothing lalala 403\n"} +{"Time":"2024-05-25T17:06:16.987045694+09:00","Action":"run","Package":"neotest_go","Test":"TestSomeTest/AccessDenied4"} +{"Time":"2024-05-25T17:06:16.987048493+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied4","Output":"=== RUN TestSomeTest/AccessDenied4\n"} +{"Time":"2024-05-25T17:06:16.987051059+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied4","Output":"AccessDenied4 GET /api/nothing lalala 403\n"} +{"Time":"2024-05-25T17:06:16.987053703+09:00","Action":"run","Package":"neotest_go","Test":"TestSomeTest/AccessDenied5"} +{"Time":"2024-05-25T17:06:16.987055897+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied5","Output":"=== RUN TestSomeTest/AccessDenied5\n"} +{"Time":"2024-05-25T17:06:16.987058733+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied5","Output":"AccessDenied5 GET /api/nothing lalala 403\n"} +{"Time":"2024-05-25T17:06:16.987062114+09:00","Action":"run","Package":"neotest_go","Test":"TestSomeTest/AccessDenied6"} +{"Time":"2024-05-25T17:06:16.987064491+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied6","Output":"=== RUN TestSomeTest/AccessDenied6\n"} +{"Time":"2024-05-25T17:06:16.987067709+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied6","Output":"AccessDenied6 GET /api/nothing lalala 403\n"} +{"Time":"2024-05-25T17:06:16.987076359+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest","Output":"--- PASS: TestSomeTest (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987079722+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied1","Output":" --- PASS: TestSomeTest/AccessDenied1 (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987082855+09:00","Action":"pass","Package":"neotest_go","Test":"TestSomeTest/AccessDenied1","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987085329+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied2","Output":" --- PASS: TestSomeTest/AccessDenied2 (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987088221+09:00","Action":"pass","Package":"neotest_go","Test":"TestSomeTest/AccessDenied2","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987090756+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied3","Output":" --- PASS: TestSomeTest/AccessDenied3 (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987094115+09:00","Action":"pass","Package":"neotest_go","Test":"TestSomeTest/AccessDenied3","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987096613+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied4","Output":" --- PASS: TestSomeTest/AccessDenied4 (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987099588+09:00","Action":"pass","Package":"neotest_go","Test":"TestSomeTest/AccessDenied4","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987104022+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied5","Output":" --- PASS: TestSomeTest/AccessDenied5 (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987107814+09:00","Action":"pass","Package":"neotest_go","Test":"TestSomeTest/AccessDenied5","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987110865+09:00","Action":"output","Package":"neotest_go","Test":"TestSomeTest/AccessDenied6","Output":" --- PASS: TestSomeTest/AccessDenied6 (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987113695+09:00","Action":"pass","Package":"neotest_go","Test":"TestSomeTest/AccessDenied6","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987116401+09:00","Action":"pass","Package":"neotest_go","Test":"TestSomeTest","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987119142+09:00","Action":"run","Package":"neotest_go","Test":"TestSplit"} +{"Time":"2024-05-25T17:06:16.987121813+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit","Output":"=== RUN TestSplit\n"} +{"Time":"2024-05-25T17:06:16.987124271+09:00","Action":"run","Package":"neotest_go","Test":"TestSplit/simple"} +{"Time":"2024-05-25T17:06:16.987126899+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/simple","Output":"=== RUN TestSplit/simple\n"} +{"Time":"2024-05-25T17:06:16.987129965+09:00","Action":"run","Package":"neotest_go","Test":"TestSplit/wrong_sep"} +{"Time":"2024-05-25T17:06:16.987132221+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/wrong_sep","Output":"=== RUN TestSplit/wrong_sep\n"} +{"Time":"2024-05-25T17:06:16.98713529+09:00","Action":"run","Package":"neotest_go","Test":"TestSplit/no_sep"} +{"Time":"2024-05-25T17:06:16.987138035+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/no_sep","Output":"=== RUN TestSplit/no_sep\n"} +{"Time":"2024-05-25T17:06:16.987140671+09:00","Action":"run","Package":"neotest_go","Test":"TestSplit/trailing_sep"} +{"Time":"2024-05-25T17:06:16.987143812+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/trailing_sep","Output":"=== RUN TestSplit/trailing_sep\n"} +{"Time":"2024-05-25T17:06:16.987148473+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/trailing_sep","Output":" map_table_test.go:25: trailing sep: expected: [a b c], got: [a b c ]\n"} +{"Time":"2024-05-25T17:06:16.987152641+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit","Output":"--- FAIL: TestSplit (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987156528+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/simple","Output":" --- PASS: TestSplit/simple (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.98716009+09:00","Action":"pass","Package":"neotest_go","Test":"TestSplit/simple","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987163018+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/wrong_sep","Output":" --- PASS: TestSplit/wrong_sep (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987166426+09:00","Action":"pass","Package":"neotest_go","Test":"TestSplit/wrong_sep","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987169756+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/no_sep","Output":" --- PASS: TestSplit/no_sep (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987173446+09:00","Action":"pass","Package":"neotest_go","Test":"TestSplit/no_sep","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987176509+09:00","Action":"output","Package":"neotest_go","Test":"TestSplit/trailing_sep","Output":" --- FAIL: TestSplit/trailing_sep (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987179658+09:00","Action":"fail","Package":"neotest_go","Test":"TestSplit/trailing_sep","Elapsed":0} +{"Time":"2024-05-25T17:06:16.9871823+09:00","Action":"fail","Package":"neotest_go","Test":"TestSplit","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987185013+09:00","Action":"run","Package":"neotest_go","Test":"TestExampleTestSuite"} +{"Time":"2024-05-25T17:06:16.987187634+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite","Output":"=== RUN TestExampleTestSuite\n"} +{"Time":"2024-05-25T17:06:16.987358969+09:00","Action":"run","Package":"neotest_go","Test":"TestExampleTestSuite/TestExample"} +{"Time":"2024-05-25T17:06:16.987372775+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExample","Output":"=== RUN TestExampleTestSuite/TestExample\n"} +{"Time":"2024-05-25T17:06:16.987378537+09:00","Action":"run","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure"} +{"Time":"2024-05-25T17:06:16.987383079+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Output":"=== RUN TestExampleTestSuite/TestExampleFailure\n"} +{"Time":"2024-05-25T17:06:16.987611537+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Output":" suite_test.go:32: \n"} +{"Time":"2024-05-25T17:06:16.987626951+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Output":" \tError Trace:\tsuite_test.go:32\n"} +{"Time":"2024-05-25T17:06:16.987631582+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Output":" \tError: \tNot equal: \n"} +{"Time":"2024-05-25T17:06:16.987635334+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Output":" \t \texpected: 5\n"} +{"Time":"2024-05-25T17:06:16.9876384+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Output":" \t \tactual : 3\n"} +{"Time":"2024-05-25T17:06:16.987641353+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Output":" \tTest: \tTestExampleTestSuite/TestExampleFailure\n"} +{"Time":"2024-05-25T17:06:16.987649622+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite","Output":"--- FAIL: TestExampleTestSuite (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987655287+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExample","Output":" --- PASS: TestExampleTestSuite/TestExample (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987659094+09:00","Action":"pass","Package":"neotest_go","Test":"TestExampleTestSuite/TestExample","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987663126+09:00","Action":"output","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Output":" --- FAIL: TestExampleTestSuite/TestExampleFailure (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987666501+09:00","Action":"fail","Package":"neotest_go","Test":"TestExampleTestSuite/TestExampleFailure","Elapsed":0} +{"Time":"2024-05-25T17:06:16.9876691+09:00","Action":"fail","Package":"neotest_go","Test":"TestExampleTestSuite","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987671645+09:00","Action":"run","Package":"neotest_go","Test":"TestOdd"} +{"Time":"2024-05-25T17:06:16.987674132+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd","Output":"=== RUN TestOdd\n"} +{"Time":"2024-05-25T17:06:16.987676921+09:00","Action":"run","Package":"neotest_go","Test":"TestOdd/odd"} +{"Time":"2024-05-25T17:06:16.987680637+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd/odd","Output":"=== RUN TestOdd/odd\n"} +{"Time":"2024-05-25T17:06:16.987683855+09:00","Action":"run","Package":"neotest_go","Test":"TestOdd/odd/5_is_odd"} +{"Time":"2024-05-25T17:06:16.98769839+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd/odd/5_is_odd","Output":"=== RUN TestOdd/odd/5_is_odd\n"} +{"Time":"2024-05-25T17:06:16.987711715+09:00","Action":"run","Package":"neotest_go","Test":"TestOdd/odd/5_is_odd/9_is_odd"} +{"Time":"2024-05-25T17:06:16.987713743+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd/odd/5_is_odd/9_is_odd","Output":"=== RUN TestOdd/odd/5_is_odd/9_is_odd\n"} +{"Time":"2024-05-25T17:06:16.987715909+09:00","Action":"run","Package":"neotest_go","Test":"TestOdd/odd/7_is_odd"} +{"Time":"2024-05-25T17:06:16.987717512+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd/odd/7_is_odd","Output":"=== RUN TestOdd/odd/7_is_odd\n"} +{"Time":"2024-05-25T17:06:16.987720928+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd","Output":"--- PASS: TestOdd (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987723417+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd/odd","Output":" --- PASS: TestOdd/odd (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987726445+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd/odd/5_is_odd","Output":" --- PASS: TestOdd/odd/5_is_odd (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987728552+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd/odd/5_is_odd/9_is_odd","Output":" --- PASS: TestOdd/odd/5_is_odd/9_is_odd (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.98773067+09:00","Action":"pass","Package":"neotest_go","Test":"TestOdd/odd/5_is_odd/9_is_odd","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987733354+09:00","Action":"pass","Package":"neotest_go","Test":"TestOdd/odd/5_is_odd","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987734868+09:00","Action":"output","Package":"neotest_go","Test":"TestOdd/odd/7_is_odd","Output":" --- PASS: TestOdd/odd/7_is_odd (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987736884+09:00","Action":"pass","Package":"neotest_go","Test":"TestOdd/odd/7_is_odd","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987738363+09:00","Action":"pass","Package":"neotest_go","Test":"TestOdd/odd","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987739718+09:00","Action":"pass","Package":"neotest_go","Test":"TestOdd","Elapsed":0} +{"Time":"2024-05-25T17:06:16.987741167+09:00","Action":"run","Package":"neotest_go","Test":"Example_hello_ok"} +{"Time":"2024-05-25T17:06:16.987742665+09:00","Action":"output","Package":"neotest_go","Test":"Example_hello_ok","Output":"=== RUN Example_hello_ok\n"} +{"Time":"2024-05-25T17:06:16.987748658+09:00","Action":"output","Package":"neotest_go","Test":"Example_hello_ok","Output":"--- PASS: Example_hello_ok (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987750589+09:00","Action":"pass","Package":"neotest_go","Test":"Example_hello_ok","Elapsed":0} +{"Time":"2024-05-25T17:06:16.98775208+09:00","Action":"run","Package":"neotest_go","Test":"Example_hello_ng"} +{"Time":"2024-05-25T17:06:16.987753501+09:00","Action":"output","Package":"neotest_go","Test":"Example_hello_ng","Output":"=== RUN Example_hello_ng\n"} +{"Time":"2024-05-25T17:06:16.987755588+09:00","Action":"output","Package":"neotest_go","Test":"Example_hello_ng","Output":"--- FAIL: Example_hello_ng (0.00s)\n"} +{"Time":"2024-05-25T17:06:16.987757621+09:00","Action":"output","Package":"neotest_go","Test":"Example_hello_ng","Output":"got:\n"} +{"Time":"2024-05-25T17:06:16.987759383+09:00","Action":"output","Package":"neotest_go","Test":"Example_hello_ng","Output":"hello world\n"} +{"Time":"2024-05-25T17:06:16.987761201+09:00","Action":"output","Package":"neotest_go","Test":"Example_hello_ng","Output":"want:\n"} +{"Time":"2024-05-25T17:06:16.987762945+09:00","Action":"output","Package":"neotest_go","Test":"Example_hello_ng","Output":"NG pattern\n"} +{"Time":"2024-05-25T17:06:16.987764982+09:00","Action":"fail","Package":"neotest_go","Test":"Example_hello_ng","Elapsed":0} +{"Time":"2024-05-25T17:06:16.988651539+09:00","Action":"output","Package":"neotest_go","Output":"FAIL\n"} +{"Time":"2024-05-25T17:06:16.988706481+09:00","Action":"output","Package":"neotest_go","Output":"FAIL\tneotest_go\t0.004s\n"} +{"Time":"2024-05-25T17:06:16.988710395+09:00","Action":"fail","Package":"neotest_go","Elapsed":0.004} From ac35284f68508a6f0997cb434e009ba548fe9373 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 30 Jun 2024 21:25:04 +0900 Subject: [PATCH 006/139] update coc-settings.json for demo --- test_proj/.vim/coc-settings.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test_proj/.vim/coc-settings.json b/test_proj/.vim/coc-settings.json index 61661a8..1c61806 100644 --- a/test_proj/.vim/coc-settings.json +++ b/test_proj/.vim/coc-settings.json @@ -3,10 +3,10 @@ "testing": { "command": "testing-language-server", "trace.server": "verbose", - "filetypes": ["rust", "javascript"], + "filetypes": ["rust", "javascript", "go"], "initializationOptions": { "adapterCommand": { - ".rs": [ + "rust": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=cargo-test"], @@ -14,13 +14,21 @@ "exclude_patterns": ["/**/target/**"] } ], - ".js": [ + "javascript": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=jest"], "include_patterns": ["/**/*.js"], "exclude_patterns": ["/node_modules/**/*"] } + ], + "go": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=go-test"], + "include_patterns": ["/**/*.go"], + "exclude_patterns": [] + } ] } } From 5f3759ec288e29d60953c5c5525afa3a5c011040 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 30 Jun 2024 22:14:21 +0900 Subject: [PATCH 007/139] fix a bug in nested workspace --- crates/adapter/src/runner/cargo_test.rs | 45 +++---------------- crates/adapter/src/runner/jest.rs | 57 +++++-------------------- crates/adapter/src/runner/util.rs | 22 +++++----- 3 files changed, 30 insertions(+), 94 deletions(-) diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 4d7f611..67bc404 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -18,6 +18,8 @@ use testing_language_server::spec::RunFileTestResultItem; use crate::model::Runner; +use super::util::detect_workspaces_from_file_paths; + // If the character value is greater than the line length it defaults back to the line length. const MAX_CHAR_LENGTH: u32 = 10000; @@ -181,41 +183,8 @@ fn discover(file_path: &str) -> Result, LSError> { Ok(test_items) } -fn detect_workspace_from_file(file_path: PathBuf) -> Option { - let parent = file_path.parent(); - if let Some(parent) = parent { - if parent.join("Cargo.toml").exists() { - return Some(parent.to_string_lossy().to_string()); - } else { - detect_workspace_from_file(parent.to_path_buf()) - } - } else { - None - } -} - -fn detect_workspaces(file_paths: Vec) -> Result { - let mut result_map: HashMap> = HashMap::new(); - let mut file_paths = file_paths.clone(); - file_paths.sort_by_key(|b| std::cmp::Reverse(b.len())); - for file_path in file_paths { - let existing_workspace = result_map - .iter() - .find(|(workspace_root, _)| file_path.contains(workspace_root.as_str())); - if let Some((workspace_root, _)) = existing_workspace { - result_map - .entry(workspace_root.to_string()) - .or_default() - .push(file_path); - } else { - let workspace = detect_workspace_from_file(PathBuf::from_str(&file_path).unwrap()); - if let Some(workspace) = workspace { - result_map.entry(workspace).or_default().push(file_path); - } - } - } - - Ok(result_map) +fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { + detect_workspaces_from_file_paths(file_paths, &["Cargo.toml".to_string()]) } #[derive(Eq, PartialEq, Hash, Debug)] @@ -263,12 +232,12 @@ impl Runner for CargoTestRunner { Ok(()) } - fn detect_workspaces_root( + fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; - let detect_result = detect_workspaces(file_paths)?; + let detect_result = detect_workspaces(&file_paths); serde_json::to_writer(std::io::stdout(), &detect_result)?; Ok(()) } @@ -350,7 +319,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace .map(|file_path| file_path.to_str().unwrap().to_string()) .collect(); - let workspaces = detect_workspaces(file_paths).unwrap(); + let workspaces = detect_workspaces(&file_paths); assert_eq!(workspaces.len(), 2); assert!(workspaces.contains_key(&absolute_path_of_test_proj.to_str().unwrap().to_string())); assert!(workspaces.contains_key(¤t_dir.to_str().unwrap().to_string())); diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 1cbc8e0..f627209 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -5,8 +5,6 @@ use regex::Regex; use serde_json::Value; use std::collections::HashMap; use std::fs; -use std::path::PathBuf; -use std::str::FromStr; use tempfile::tempdir; use testing_language_server::error::LSError; @@ -22,6 +20,8 @@ use tree_sitter::QueryCursor; use crate::model::Runner; +use super::util::detect_workspaces_from_file_paths; + // If the character value is greater than the line length it defaults back to the line length. const MAX_CHAR_LENGTH: u32 = 10000; @@ -81,43 +81,8 @@ fn parse_diagnostics( .collect()) } -fn detect_workspace_from_file(file_path: PathBuf) -> Option { - let parent = file_path.parent(); - if let Some(parent) = parent { - if parent.join("package.json").exists() { - return Some(parent.to_string_lossy().to_string()); - } else { - detect_workspace_from_file(parent.to_path_buf()) - } - } else { - None - } -} - -fn detect_workspaces(file_paths: Vec) -> Result { - let mut result_map: HashMap> = HashMap::new(); - let mut file_paths: Vec = file_paths - .into_iter() - .filter(|path| !path.contains("node_modules/")) - .collect(); - file_paths.sort_by_key(|b| std::cmp::Reverse(b.len())); - for file_path in file_paths { - let existing_workspace = result_map - .iter() - .find(|(workspace_root, _)| file_path.contains(workspace_root.as_str())); - if let Some((workspace_root, _)) = existing_workspace { - result_map - .entry(workspace_root.to_string()) - .or_default() - .push(file_path); - } else { - let workspace = detect_workspace_from_file(PathBuf::from_str(&file_path).unwrap()); - if let Some(workspace) = workspace { - result_map.entry(workspace).or_default().push(file_path); - } - } - } - Ok(result_map) +fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { + detect_workspaces_from_file_paths(&file_paths, &["package.json".to_string()]) } fn discover(file_path: &str) -> Result, LSError> { @@ -303,12 +268,12 @@ impl Runner for JestRunner { Ok(()) } - fn detect_workspaces_root( + fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; - let detect_result = detect_workspaces(file_paths)?; + let detect_result = detect_workspaces(file_paths); serde_json::to_writer(std::io::stdout(), &detect_result)?; Ok(()) } @@ -346,7 +311,7 @@ mod tests { .iter() .map(|file_path| file_path.to_str().unwrap().to_string()) .collect(); - let detect_result = detect_workspaces(file_paths).unwrap(); + let detect_result = detect_workspaces(file_paths); assert_eq!(detect_result.len(), 1); detect_result.iter().for_each(|(workspace, _)| { assert_eq!(workspace, absolute_path_of_test_proj.to_str().unwrap()); @@ -365,21 +330,21 @@ mod tests { name: String::from("fail"), start_position: Range { start: Position { - line: 2, + line: 1, character: 2 }, end: Position { - line: 2, + line: 1, character: MAX_CHAR_LENGTH } }, end_position: Range { start: Position { - line: 4, + line: 3, character: 0 }, end: Position { - line: 4, + line: 3, character: 4 } } diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index 863decc..d0ad3ec 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -25,7 +25,7 @@ pub fn detect_workspaces_from_file_paths( ) -> HashMap> { let mut result_map: HashMap> = HashMap::new(); let mut file_paths = target_file_paths.to_vec(); - file_paths.sort_by_key(|b| std::cmp::Reverse(b.len())); + file_paths.sort_by_key(|b| b.len()); for file_path in file_paths { let existing_workspace = result_map .iter() @@ -35,15 +35,17 @@ pub fn detect_workspaces_from_file_paths( .entry(workspace_root.to_string()) .or_default() .push(file_path.clone()); - } else { - let workspace = - detect_workspace_from_file(PathBuf::from_str(&file_path).unwrap(), file_names); - if let Some(workspace) = workspace { - result_map - .entry(workspace) - .or_default() - .push(file_path.clone()); - } + } + // Push the file path to the found workspace even if the existing_workspace becomes Some. + // In some cases, the simple method of finding a workspace, such as the relationship + // between the project root and the adapter crate in this repository, does not work. + let workspace = + detect_workspace_from_file(PathBuf::from_str(&file_path).unwrap(), file_names); + if let Some(workspace) = workspace { + result_map + .entry(workspace) + .or_default() + .push(file_path.clone()); } } result_map From 51738a9a456719b2cb3d6b3458aa15744495b2e4 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 30 Jun 2024 22:17:28 +0900 Subject: [PATCH 008/139] add GHA workflow for CI --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5f3bde8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: Rust CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + + - name: Build (required step) + run: cargo build --workspace + + - name: Run tests + run: cargo test --verbose --workspace -- --nocapture From caf868f9bdb6f824580fc0e9c10ffa3b875921dc Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 30 Jun 2024 22:39:44 +0900 Subject: [PATCH 009/139] add license --- LICENSE | 21 +++++++++++++++++++++ crates/adapter/src/runner/cargo_test.rs | 2 ++ crates/adapter/src/runner/go.rs | 2 ++ crates/adapter/src/runner/jest.rs | 2 ++ 4 files changed, 27 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a3428a9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Kodai Kabasawa + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 67bc404..8b56372 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -87,6 +87,8 @@ fn discover(file_path: &str) -> Result, LSError> { .expect("Error loading Rust grammar"); let source_code = std::fs::read_to_string(file_path)?; let tree = parser.parse(&source_code, None).unwrap(); + // from https://github.com/rouge8/neotest-rust/blob/0418811e1e3499b2501593f2e131d02f5e6823d4/lua/neotest-rust/init.lua#L167 + // license: https://github.com/rouge8/neotest-rust/blob/0418811e1e3499b2501593f2e131d02f5e6823d4/LICENSE let query_string = r#" ( (attribute_item diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index f743f77..f71432e 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -144,6 +144,8 @@ fn discover(file_path: &str) -> Result, LSError> { .expect("Error loading Rust grammar"); let source_code = std::fs::read_to_string(file_path)?; let tree = parser.parse(&source_code, None).unwrap(); + // from https://github.com/nvim-neotest/neotest-go/blob/92950ad7be2ca02a41abca5c6600ff6ffaf5b5d6/lua/neotest-go/init.lua#L54 + // license: https://github.com/nvim-neotest/neotest-go/blob/92950ad7be2ca02a41abca5c6600ff6ffaf5b5d6/README.md let query_string = r#" ;;query ((function_declaration diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index f627209..441c40d 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -93,6 +93,8 @@ fn discover(file_path: &str) -> Result, LSError> { .expect("Error loading JavaScript grammar"); let source_code = std::fs::read_to_string(file_path)?; let tree = parser.parse(&source_code, None).unwrap(); + // from https://github.com/nvim-neotest/neotest-jest/blob/514fd4eae7da15fd409133086bb8e029b65ac43f/lua/neotest-jest/init.lua#L162 + // license: https://github.com/nvim-neotest/neotest-jest/blob/514fd4eae7da15fd409133086bb8e029b65ac43f/LICENSE.md let query_string = r#" ; -- Namespaces -- ; Matches: `describe('context', () => {})` From b86e08e588474261259e27a356849b4084e1143c Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 30 Jun 2024 22:42:07 +0900 Subject: [PATCH 010/139] update README --- test_proj/go/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test_proj/go/README.md b/test_proj/go/README.md index 5824146..a6e5270 100644 --- a/test_proj/go/README.md +++ b/test_proj/go/README.md @@ -1 +1,3 @@ This directory is from https://github.com/nvim-neotest/neotest-go/tree/main/neotest_go. + +LICENSE: https://github.com/nvim-neotest/neotest-go/blob/main/LICENSE.md From f9c054ebd31596b5cdc250412e76456fc46099e4 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 6 Jul 2024 11:20:41 +0900 Subject: [PATCH 011/139] organize modules --- src/language.rs | 46 ---------------------------------------------- src/lib.rs | 3 --- src/main.rs | 10 ++++++++-- src/util.rs | 5 ----- 4 files changed, 8 insertions(+), 56 deletions(-) delete mode 100644 src/language.rs diff --git a/src/language.rs b/src/language.rs deleted file mode 100644 index fd6867d..0000000 --- a/src/language.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::collections::HashMap; -use std::str::FromStr; -use strum::{AsRefStr, Display}; - -use once_cell::sync::Lazy; - -type Extension<'a> = &'a str; - -#[derive(Display, AsRefStr, Eq, PartialEq, Hash)] -pub enum AvailableFileType { - #[strum(serialize = "rust")] - Rust, - #[strum(serialize = "javascript")] - Javascript, - #[strum(serialize = "javascriptreact")] - JavascriptReact, - #[strum(serialize = "typescript")] - Typescript, - #[strum(serialize = "typescriptreact")] - TypescriptReact, -} - -impl FromStr for AvailableFileType { - type Err = String; - - fn from_str(s: &str) -> Result { - match s { - "rust" => Ok(AvailableFileType::Rust), - "javascript" => Ok(AvailableFileType::Javascript), - "javascriptreact" => Ok(AvailableFileType::JavascriptReact), - "typescript" => Ok(AvailableFileType::Typescript), - "typescriptreact" => Ok(AvailableFileType::TypescriptReact), - _ => Err(format!("Unknown file type: {}", s)), - } - } -} - -pub static LANGUAGE_ID_MAP: Lazy>> = Lazy::new(|| { - let mut map = HashMap::new(); - map.insert(AvailableFileType::Rust, vec!["rs"]); - map.insert(AvailableFileType::Javascript, vec!["js", "jsx"]); - map.insert(AvailableFileType::JavascriptReact, vec!["js", "jsx"]); - map.insert(AvailableFileType::Typescript, vec!["ts", "tsx"]); - map.insert(AvailableFileType::TypescriptReact, vec!["ts", "tsx"]); - map -}); diff --git a/src/lib.rs b/src/lib.rs index a107420..edbc74f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,3 @@ pub mod error; -pub mod language; -pub mod log; -pub mod server; pub mod spec; pub mod util; diff --git a/src/main.rs b/src/main.rs index bdd712b..3cebd00 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,11 @@ -use testing_language_server::log::Log; -use testing_language_server::server::TestingLS; +mod error; +mod log; +mod server; +mod spec; +mod util; + +use crate::log::Log; +use crate::server::TestingLS; fn main() { let mut server = TestingLS::new(); diff --git a/src/util.rs b/src/util.rs index 0787ac9..6cacdf5 100644 --- a/src/util.rs +++ b/src/util.rs @@ -3,11 +3,6 @@ use serde::Serialize; use std::io::stdout; use std::io::Write; -/// Returns the extension which includes `.` from the url string -pub fn extension_from_url_str(url_str: &str) -> Option { - Some(String::from(".") + url_str.split('.').last().unwrap()) -} - pub fn send_stdout(message: &T) -> Result<(), LSError> where T: ?Sized + Serialize + std::fmt::Debug, From 60e352f24f92f00fb023e146b59bc7614c5a659f Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 6 Jul 2024 15:54:02 +0900 Subject: [PATCH 012/139] list project files correctly --- Cargo.lock | 104 +++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/server.rs | 43 +++++++------ src/spec.rs | 6 +- test_proj/.vim/coc-settings.json | 4 +- test_proj/jest/another.spec.js | 11 ++-- 6 files changed, 136 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bbce75..0daac9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,6 +77,16 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "cc" version = "1.0.96" @@ -144,6 +154,25 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -222,6 +251,30 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "globset" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" +dependencies = [ + "bitflags 2.5.0", + "ignore", + "walkdir", +] + [[package]] name = "heck" version = "0.4.1" @@ -244,6 +297,22 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ignore" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "itoa" version = "1.0.11" @@ -278,6 +347,12 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + [[package]] name = "lsp-types" version = "0.95.1" @@ -416,6 +491,15 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.198" @@ -526,6 +610,7 @@ dependencies = [ "clap", "dirs", "glob", + "globwalk", "lsp-types", "once_cell", "regex", @@ -791,12 +876,31 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 1ca1cf0..2ef64bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,3 +46,4 @@ clap = { workspace = true } once_cell = { workspace = true } strum = { workspace = true, features = ["derive"] } glob = { workspace = true } +globwalk = "0.9.1" diff --git a/src/server.rs b/src/server.rs index 32e2bfe..7e28116 100644 --- a/src/server.rs +++ b/src/server.rs @@ -8,7 +8,6 @@ use crate::spec::RunFileTestResultItem; use crate::spec::WorkspaceAnalysis; use crate::util::format_uri; use crate::util::send_stdout; -use glob::glob; use glob::Pattern; use lsp_types::Diagnostic; use lsp_types::DiagnosticOptions; @@ -130,7 +129,9 @@ impl TestingLS { let value: Value = serde_json::from_str(&message)?; let method = &value["method"].as_str(); + tracing::info!("method={:#?}", method); let params = &value["params"]; + tracing::info!("params={:#?}", params); if let Some(method) = method { match *method { @@ -197,25 +198,25 @@ impl TestingLS { exclude_patterns: &[String], ) -> Vec { let mut result: Vec = vec![]; - let base_dir = base_dir.to_string_lossy().to_string(); let exclude_pattern = exclude_patterns .iter() .filter_map(|exclude_pattern| { - Pattern::new(&format!("!{base_dir}{exclude_pattern}")).ok() + Pattern::new(base_dir.join(exclude_pattern).to_str().unwrap()).ok() }) .collect::>(); - for include_pattern in include_patterns { - let matched = glob(format!("{base_dir}{include_pattern}").as_str()); - if let Ok(entries) = matched { - for path in entries.flatten() { - let should_exclude = exclude_pattern - .iter() - .any(|exclude_pattern| exclude_pattern.matches(path.to_str().unwrap())); - if !should_exclude { - result.push(path.display().to_string()); - } - } + let base_dir = base_dir.to_str().unwrap(); + let entries = globwalk::GlobWalkerBuilder::from_patterns(base_dir, include_patterns) + .follow_links(true) + .build() + .unwrap() + .filter_map(Result::ok); + for path in entries { + let should_exclude = exclude_pattern + .iter() + .any(|exclude_pattern| exclude_pattern.matches(path.path().to_str().unwrap())); + if !should_exclude { + result.push(path.path().to_str().unwrap().to_owned()); } } result @@ -458,7 +459,7 @@ impl TestingLS { })) .unwrap(); let progress_begin = WorkDoneProgressBegin { - title: format!("Testing by adapter: {}", adapter.path), + title: "Testing".to_string(), cancellable: Some(false), message: Some(format!("testing {} files ...", paths.len())), percentage: Some(0), @@ -553,7 +554,6 @@ impl TestingLS { #[cfg(test)] mod tests { - use crate::util::extension_from_url_str; use lsp_types::{Url, WorkspaceFolder}; use std::collections::HashMap; @@ -636,18 +636,17 @@ mod tests { let files = TestingLS::project_files( &absolute_path_of_test_proj.clone(), &["/rust/src/lib.rs".to_string()], - &["/rust/src/target/**/*".to_string()], + &["/rust/target/**/*".to_string()], ); let librs = absolute_path_of_test_proj.join("rust/src/lib.rs"); assert_eq!(files, vec![librs.to_str().unwrap()]); let files = TestingLS::project_files( &absolute_path_of_test_proj.clone(), - &["**/*.js".to_string()], - &["**/node_modules/**/*".to_string()], + &["jest/*.spec.js".to_string()], + &["jest/another.spec.js".to_string()], ); - files.iter().for_each(|file| { - assert_eq!(extension_from_url_str(file).unwrap(), ".js"); - }); + let test_file = absolute_path_of_test_proj.join("jest/index.spec.js"); + assert_eq!(files, vec![test_file.to_str().unwrap()]); } #[test] diff --git a/src/spec.rs b/src/spec.rs index cb073ba..2d22505 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -43,9 +43,9 @@ pub struct DetectWorkspaceArgs { pub extra: Vec, } -pub(crate) type AdapterId = String; -pub(crate) type FilePath = String; -pub(crate) type WorkspaceFilePath = String; +pub type AdapterId = String; +pub type FilePath = String; +pub type WorkspaceFilePath = String; #[derive(Debug, Serialize, Clone)] pub struct WorkspaceAnalysis { diff --git a/test_proj/.vim/coc-settings.json b/test_proj/.vim/coc-settings.json index 1c61806..27a4349 100644 --- a/test_proj/.vim/coc-settings.json +++ b/test_proj/.vim/coc-settings.json @@ -10,7 +10,7 @@ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=cargo-test"], - "include_patterns": ["/**/*.rs"], + "include_patterns": ["/**/src/**/*.rs"], "exclude_patterns": ["/**/target/**"] } ], @@ -19,7 +19,7 @@ "path": "testing-ls-adapter", "extra_args": ["--test-kind=jest"], "include_patterns": ["/**/*.js"], - "exclude_patterns": ["/node_modules/**/*"] + "exclude_patterns": ["/**/node_modules/**/*"] } ], "go": [ diff --git a/test_proj/jest/another.spec.js b/test_proj/jest/another.spec.js index 2ea90ae..f2ad3c0 100644 --- a/test_proj/jest/another.spec.js +++ b/test_proj/jest/another.spec.js @@ -1,10 +1,9 @@ describe("another", () => { - it("fail", () => { - expect(1).toBe(0) - }) + expect(1).toBe(0); + }); it("pass", () => { - expect(1).toBe(1) - }) -}) + expect(1).toBe(1); + }); +}); From 1b74a7ad4f2292683181150749829a2b3f0d1010 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 6 Jul 2024 15:54:20 +0900 Subject: [PATCH 013/139] add adapter log --- crates/adapter/src/runner/cargo_test.rs | 22 +++++++++++++++++++--- crates/adapter/src/runner/go.rs | 13 +++++++------ crates/adapter/src/runner/jest.rs | 7 ++++--- crates/adapter/src/runner/util.rs | 12 ++++++++++++ 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 8b56372..d6cc9b4 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -1,3 +1,4 @@ +use crate::runner::util::send_stdout; use std::collections::HashMap; use std::path::PathBuf; use std::process::Output; @@ -204,7 +205,7 @@ impl Runner for CargoTestRunner { path: file_path, }); } - serde_json::to_writer(std::io::stdout(), &discover_results)?; + send_stdout(&discover_results)?; Ok(()) } @@ -213,11 +214,26 @@ impl Runner for CargoTestRunner { args: testing_language_server::spec::RunFileTestArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; + let tests = file_paths + .iter() + .map(|path| { + discover(path).map(|test_items| { + test_items + .into_iter() + .map(|item| item.id) + .collect::>() + }) + }) + .filter_map(Result::ok) + .flatten() + .collect::>(); let workspace_root = args.workspace; let test_result = std::process::Command::new("cargo") .current_dir(&workspace_root) .arg("test") .args(args.extra) + .arg("--") + .args(tests) .output() .unwrap(); let Output { stdout, stderr, .. } = test_result; @@ -230,7 +246,7 @@ impl Runner for CargoTestRunner { PathBuf::from_str(&workspace_root).unwrap(), &file_paths, ); - serde_json::to_writer(std::io::stdout(), &diagnostics)?; + send_stdout(&diagnostics)?; Ok(()) } @@ -240,7 +256,7 @@ impl Runner for CargoTestRunner { ) -> Result<(), LSError> { let file_paths = args.file_paths; let detect_result = detect_workspaces(&file_paths); - serde_json::to_writer(std::io::stdout(), &detect_result)?; + send_stdout(&detect_result)?; Ok(()) } } diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index f71432e..c765449 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -1,4 +1,5 @@ use crate::model::Runner; +use crate::runner::util::send_stdout; use anyhow::anyhow; use lsp_types::Diagnostic; use lsp_types::Position; @@ -306,7 +307,7 @@ impl Runner for GoTestRunner { path: file_path, }); } - serde_json::to_writer(std::io::stdout(), &discover_results)?; + send_stdout(&discover_results)?; Ok(()) } @@ -334,7 +335,7 @@ impl Runner for GoTestRunner { PathBuf::from_str(&workspace).unwrap(), &file_paths, )?; - serde_json::to_writer(std::io::stdout(), &diagnostics)?; + send_stdout(&diagnostics)?; Ok(()) } @@ -342,10 +343,10 @@ impl Runner for GoTestRunner { &self, args: testing_language_server::spec::DetectWorkspaceArgs, ) -> Result<(), testing_language_server::error::LSError> { - serde_json::to_writer( - std::io::stdout(), - &detect_workspaces_from_file_paths(&args.file_paths, &["go.mod".to_string()]), - )?; + send_stdout(&detect_workspaces_from_file_paths( + &args.file_paths, + &["go.mod".to_string()], + ))?; Ok(()) } } diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 441c40d..700dde3 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -1,3 +1,4 @@ +use crate::runner::util::send_stdout; use lsp_types::Diagnostic; use lsp_types::Position; use lsp_types::Range; @@ -238,7 +239,7 @@ impl Runner for JestRunner { path: file_path, }) } - serde_json::to_writer(std::io::stdout(), &discover_results)?; + send_stdout(&discover_results)?; Ok(()) } @@ -266,7 +267,7 @@ impl Runner for JestRunner { .unwrap(); let test_result = fs::read_to_string(tempfile_path)?; let diagnostics: RunFileTestResult = parse_diagnostics(&test_result, file_paths)?; - serde_json::to_writer(std::io::stdout(), &diagnostics)?; + send_stdout(&diagnostics)?; Ok(()) } @@ -276,7 +277,7 @@ impl Runner for JestRunner { ) -> Result<(), LSError> { let file_paths = args.file_paths; let detect_result = detect_workspaces(file_paths); - serde_json::to_writer(std::io::stdout(), &detect_result)?; + send_stdout(&detect_result)?; Ok(()) } } diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index d0ad3ec..5310fa9 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -2,6 +2,9 @@ use std::collections::HashMap; use std::path::PathBuf; use std::str::FromStr; +use serde::Serialize; +use testing_language_server::error::LSError; + /// determine if a particular file is the root of workspace based on whether it is in the same directory pub fn detect_workspace_from_file(file_path: PathBuf, file_names: &[String]) -> Option { let parent = file_path.parent(); @@ -50,3 +53,12 @@ pub fn detect_workspaces_from_file_paths( } result_map } + +pub fn send_stdout(value: &T) -> Result<(), LSError> +where + T: ?Sized + Serialize + std::fmt::Debug, +{ + tracing::info!("adapter stdout: {:#?}", value); + serde_json::to_writer(std::io::stdout(), &value)?; + Ok(()) +} From 0ae8988cc53f18cceb59299c393941f6e6750944 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 13 Jul 2024 12:06:38 +0900 Subject: [PATCH 014/139] add feature to configure workspace directory close #16 --- .vim/coc-settings.json | 17 +++++++++ src/server.rs | 53 ++++++++++++++++----------- src/spec.rs | 3 +- src/util.rs | 83 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 23 deletions(-) create mode 100644 .vim/coc-settings.json diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json new file mode 100644 index 0000000..f66ce6e --- /dev/null +++ b/.vim/coc-settings.json @@ -0,0 +1,17 @@ +{ + "testing.enable": true, + "testing.fileTypes": ["rust"], + "testing.adapterCommand": { + "rust": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=cargo-test", "--workspace"], + "include_patterns": ["/**/*.rs"], + "exclude_patterns": ["/test_proj/**/*"], + "workspace_dir": "." + } + ] + }, + "testing.server.path": "testing-language-server", + "testing.trace.server": "verbose" +} diff --git a/src/server.rs b/src/server.rs index 7e28116..63111e1 100644 --- a/src/server.rs +++ b/src/server.rs @@ -7,6 +7,7 @@ use crate::spec::RunFileTestResult; use crate::spec::RunFileTestResultItem; use crate::spec::WorkspaceAnalysis; use crate::util::format_uri; +use crate::util::resolve_path; use crate::util::send_stdout; use glob::Pattern; use lsp_types::Diagnostic; @@ -35,6 +36,7 @@ use serde::Deserialize; use serde_json::json; use serde_json::Value; use std::collections::HashMap; +use std::env::current_dir; use std::io::BufRead; use std::io::{self, Read}; use std::path::Path; @@ -46,7 +48,6 @@ use std::process::Output; #[serde(rename_all = "camelCase")] pub struct InitializedOptions { adapter_command: HashMap>, - project_dir: Option, } pub struct TestingLS { @@ -71,18 +72,18 @@ impl TestingLS { } fn project_dir(&self) -> Result { - let default_project_dir = self - .initialize_params - .clone() - .workspace_folders - .ok_or(LSError::Any(anyhow::anyhow!("No workspace folders found")))?; - let default_workspace_uri = default_project_dir[0].uri.clone(); - let project_dir = self - .options - .project_dir - .clone() - .unwrap_or(default_workspace_uri.to_file_path().unwrap()); - Ok(project_dir) + let cwd = current_dir(); + if let Ok(cwd) = cwd { + Ok(cwd) + } else { + let default_project_dir = self + .initialize_params + .clone() + .workspace_folders + .ok_or(LSError::Any(anyhow::anyhow!("No workspace folders found")))?; + let default_workspace_uri = default_project_dir[0].uri.clone(); + Ok(default_workspace_uri.to_file_path().unwrap()) + } } pub fn main_loop(&mut self) -> Result<(), LSError> { @@ -278,6 +279,8 @@ impl TestingLS { envs, include_patterns, exclude_patterns, + workspace_dir, + .. } = &adapter; let file_paths = Self::project_files(&project_dir, include_patterns, exclude_patterns); @@ -301,6 +304,19 @@ impl TestingLS { let adapter_result = String::from_utf8(output.stdout) .map_err(|err| LSError::Adapter(err.to_string()))?; let workspace: DetectWorkspaceResult = serde_json::from_str(&adapter_result)?; + let workspace = if let Some(workspace_dir) = workspace_dir { + let workspace_dir = resolve_path(&project_dir, workspace_dir) + .to_str() + .unwrap() + .to_string(); + let target_paths = workspace + .into_iter() + .flat_map(|kv| kv.1) + .collect::>(); + HashMap::from([(workspace_dir.clone(), target_paths)]) + } else { + workspace + }; self.workspaces_cache .push(WorkspaceAnalysis::new(adapter.clone(), workspace)) } @@ -572,7 +588,6 @@ mod tests { }, options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![])]), - project_dir: None, }, workspaces_cache: Vec::new(), }; @@ -593,9 +608,7 @@ mod tests { let adapter_conf = AdapterConfiguration { path: abs_path_of_rust_adapter, extra_args: vec!["--test-kind=cargo-test".to_string()], - envs: HashMap::new(), - include_patterns: vec![], - exclude_patterns: vec![], + ..Default::default() }; let mut server = TestingLS { initialize_params: InitializeParams { @@ -607,7 +620,6 @@ mod tests { }, options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![adapter_conf])]), - project_dir: None, }, workspaces_cache: Vec::new(), }; @@ -659,9 +671,7 @@ mod tests { .unwrap() .to_string(), extra_args: vec!["--invalid-arg".to_string()], - envs: HashMap::new(), - include_patterns: vec![], - exclude_patterns: vec![], + ..Default::default() }; let abs_path_of_test_proj = std::env::current_dir().unwrap().join("test_proj/rust"); let files = TestingLS::project_files( @@ -680,7 +690,6 @@ mod tests { }, options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![adapter_conf.clone()])]), - project_dir: None, }, workspaces_cache: Vec::new(), }; diff --git a/src/spec.rs b/src/spec.rs index 2d22505..a9418f1 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -62,7 +62,7 @@ impl WorkspaceAnalysis { } } -#[derive(Debug, Deserialize, Clone, Serialize)] +#[derive(Debug, Deserialize, Clone, Serialize, Default)] pub struct AdapterConfiguration { pub path: String, #[serde(default)] @@ -71,6 +71,7 @@ pub struct AdapterConfiguration { pub envs: HashMap, pub include_patterns: Vec, pub exclude_patterns: Vec, + pub workspace_dir: Option, } pub type DetectWorkspaceResult = HashMap>; diff --git a/src/util.rs b/src/util.rs index 6cacdf5..04adad7 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,6 +2,8 @@ use crate::error::LSError; use serde::Serialize; use std::io::stdout; use std::io::Write; +use std::path::Path; +use std::path::PathBuf; pub fn send_stdout(message: &T) -> Result<(), LSError> where @@ -18,3 +20,84 @@ where pub fn format_uri(uri: &str) -> String { uri.replace("file://", "") } + +pub fn resolve_path(base_dir: &Path, relative_path: &str) -> PathBuf { + let absolute = if Path::new(relative_path).is_absolute() { + PathBuf::from(relative_path) + } else { + base_dir.join(relative_path) + }; + + let mut components = Vec::new(); + for component in absolute.components() { + match component { + std::path::Component::ParentDir => { + components.pop(); + } + std::path::Component::Normal(_) | std::path::Component::RootDir => { + components.push(component); + } + _ => {} + } + } + + PathBuf::from_iter(components) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_resolve_path() { + let base_dir = PathBuf::from("/Users/test/projects"); + + // relative path + assert_eq!( + resolve_path(&base_dir, "github.com/hoge/fuga"), + PathBuf::from("/Users/test/projects/github.com/hoge/fuga") + ); + + // current directory + assert_eq!( + resolve_path(&base_dir, "./github.com/hoge/fuga"), + PathBuf::from("/Users/test/projects/github.com/hoge/fuga") + ); + + // parent directory + assert_eq!( + resolve_path(&base_dir, "../other/project"), + PathBuf::from("/Users/test/other/project") + ); + + // multiple .. + assert_eq!( + resolve_path(&base_dir, "foo/bar/../../../baz"), + PathBuf::from("/Users/test/baz") + ); + + // absolute path + assert_eq!( + resolve_path(&base_dir, "/absolute/path"), + PathBuf::from("/absolute/path") + ); + + // empty relative path + assert_eq!( + resolve_path(&base_dir, ""), + PathBuf::from("/Users/test/projects") + ); + + // ending / + assert_eq!( + resolve_path(&base_dir, "github.com/hoge/fuga/"), + PathBuf::from("/Users/test/projects/github.com/hoge/fuga") + ); + + // complex path + assert_eq!( + resolve_path(&base_dir, "./foo/../bar/./baz/../qux/"), + PathBuf::from("/Users/test/projects/bar/qux") + ); + } +} From 3f88f9b1b61b74720f4477a6431ab854f2c6b516 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 15 Jul 2024 19:07:44 +0900 Subject: [PATCH 015/139] add vitest demo --- test_proj/.vim/coc-settings.json | 19 +- test_proj/jest/bun.lockb | Bin 116036 -> 116036 bytes test_proj/vitest/.gitignore | 2 + test_proj/vitest/.yarnrc.yml | 1 + test_proj/vitest/basic.test.ts | 12 + test_proj/vitest/package.json | 16 + test_proj/vitest/vite.config.ts | 13 + test_proj/vitest/yarn.lock | 1575 ++++++++++++++++++++++++++++++ 8 files changed, 1634 insertions(+), 4 deletions(-) create mode 100644 test_proj/vitest/.gitignore create mode 100644 test_proj/vitest/.yarnrc.yml create mode 100644 test_proj/vitest/basic.test.ts create mode 100644 test_proj/vitest/package.json create mode 100644 test_proj/vitest/vite.config.ts create mode 100644 test_proj/vitest/yarn.lock diff --git a/test_proj/.vim/coc-settings.json b/test_proj/.vim/coc-settings.json index 27a4349..e71c005 100644 --- a/test_proj/.vim/coc-settings.json +++ b/test_proj/.vim/coc-settings.json @@ -3,7 +3,7 @@ "testing": { "command": "testing-language-server", "trace.server": "verbose", - "filetypes": ["rust", "javascript", "go"], + "filetypes": ["rust", "javascript", "go", "typescript"], "initializationOptions": { "adapterCommand": { "rust": [ @@ -14,12 +14,23 @@ "exclude_patterns": ["/**/target/**"] } ], - "javascript": [ + "jest": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=jest"], - "include_patterns": ["/**/*.js"], - "exclude_patterns": ["/**/node_modules/**/*"] + "include_patterns": ["/jest/*.js"], + "exclude_patterns": ["/jest/**/node_modules/**/*"] + } + ], + "vitest": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=vitest"], + "include_patterns": [ + "/vitest/*.test.ts", + "/vitest/config/**/*.test.ts" + ], + "exclude_patterns": ["/vitest/**/node_modules/**/*"] } ], "go": [ diff --git a/test_proj/jest/bun.lockb b/test_proj/jest/bun.lockb index e3c33594aec891c927df39b29a3461db49bc849a..c177b10a55bdd09e3002736f016caf29eb92c122 100755 GIT binary patch delta 27 jcmX@o#eSrVy { + test("pass", async () => { + assert(false); + }); + + test("fail", async () => { + assert(false); + }); +}); diff --git a/test_proj/vitest/package.json b/test_proj/vitest/package.json new file mode 100644 index 0000000..4069602 --- /dev/null +++ b/test_proj/vitest/package.json @@ -0,0 +1,16 @@ +{ + "name": "spec", + "version": "0.0.1", + "description": "neotest-vitest spec", + "main": "index.js", + "license": "MIT", + "dependencies": { + "ts-node": "^10.8.2", + "typescript": "^4.7.4" + }, + "devDependencies": { + "@types/node": "^18.0.3", + "vite": "^3.0.9", + "vitest": "^0.22.1" + } +} diff --git a/test_proj/vitest/vite.config.ts b/test_proj/vitest/vite.config.ts new file mode 100644 index 0000000..a872742 --- /dev/null +++ b/test_proj/vitest/vite.config.ts @@ -0,0 +1,13 @@ +/// + +// Configure Vitest (https://vitest.dev/config/) + +import { defineConfig } from 'vite' + +export default defineConfig({ + test: { + /* for example, use global to avoid globals imports (describe, test, expect): */ + // globals: true, + }, +}) + diff --git a/test_proj/vitest/yarn.lock b/test_proj/vitest/yarn.lock new file mode 100644 index 0000000..90eb480 --- /dev/null +++ b/test_proj/vitest/yarn.lock @@ -0,0 +1,1575 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" + dependencies: + "@jridgewell/trace-mapping": "npm:0.3.9" + checksum: 10c0/05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.14.54": + version: 0.14.54 + resolution: "@esbuild/linux-loong64@npm:0.14.54" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.0.3": + version: 3.1.0 + resolution: "@jridgewell/resolve-uri@npm:3.1.0" + checksum: 10c0/78055e2526108331126366572045355051a930f017d1904a4f753d3f4acee8d92a14854948095626f6163cffc24ea4e3efa30637417bb866b84743dec7ef6fd9 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10": + version: 1.4.14 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" + checksum: 10c0/3fbaff1387c1338b097eeb6ff92890d7838f7de0dde259e4983763b44540bfd5ca6a1f7644dc8ad003a57f7e80670d5b96a8402f1386ba9aee074743ae9bad51 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.0.3" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + checksum: 10c0/fa425b606d7c7ee5bfa6a31a7b050dd5814b4082f318e0e4190f991902181b4330f43f4805db1dd4f2433fd0ed9cc7a7b9c2683f1deeab1df1b0a98b1e24055b + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"@tsconfig/node10@npm:^1.0.7": + version: 1.0.9 + resolution: "@tsconfig/node10@npm:1.0.9" + checksum: 10c0/c176a2c1e1b16be120c328300ea910df15fb9a5277010116d26818272341a11483c5a80059389d04edacf6fd2d03d4687ad3660870fdd1cc0b7109e160adb220 + languageName: node + linkType: hard + +"@tsconfig/node12@npm:^1.0.7": + version: 1.0.11 + resolution: "@tsconfig/node12@npm:1.0.11" + checksum: 10c0/dddca2b553e2bee1308a056705103fc8304e42bb2d2cbd797b84403a223b25c78f2c683ec3e24a095e82cd435387c877239bffcb15a590ba817cd3f6b9a99fd9 + languageName: node + linkType: hard + +"@tsconfig/node14@npm:^1.0.0": + version: 1.0.3 + resolution: "@tsconfig/node14@npm:1.0.3" + checksum: 10c0/67c1316d065fdaa32525bc9449ff82c197c4c19092b9663b23213c8cbbf8d88b6ed6a17898e0cbc2711950fbfaf40388938c1c748a2ee89f7234fc9e7fe2bf44 + languageName: node + linkType: hard + +"@tsconfig/node16@npm:^1.0.2": + version: 1.0.3 + resolution: "@tsconfig/node16@npm:1.0.3" + checksum: 10c0/451a0d4b2bc35c2cdb30a49b6c699d797b8bbac99b883237659698678076d4193050d90e2ee36016ccbca57075cdb073cadab38cedc45119bac68ab331958cbc + languageName: node + linkType: hard + +"@types/chai-subset@npm:^1.3.3": + version: 1.3.3 + resolution: "@types/chai-subset@npm:1.3.3" + dependencies: + "@types/chai": "npm:*" + checksum: 10c0/2dfb3210ce8d872288bb44329a44d4d1b7be360c72e8eb570a535c0e97246a4bd0209df304427d0e179c9e1c659d5dba07c25bdae13ef983edf41db81278fda5 + languageName: node + linkType: hard + +"@types/chai@npm:*, @types/chai@npm:^4.3.3": + version: 4.3.3 + resolution: "@types/chai@npm:4.3.3" + checksum: 10c0/4129cb6119d65166cc082cecca97ddcf7d24785a4a55de2e06f3f1dc4c9543340168833ebdbc16685838cdea388854badc1453393dc90597725decfc20e05aff + languageName: node + linkType: hard + +"@types/node@npm:*, @types/node@npm:^18.0.3": + version: 18.7.8 + resolution: "@types/node@npm:18.7.8" + checksum: 10c0/ce4d37ff77ef2e1a180a2a4fc26e4df4f5b7af39f555500aa2fbb96c364e67b36f65ef100be183ef1e4f382767265ae22f1c2d8eb1b40606a9fe8d03296889b8 + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 + languageName: node + linkType: hard + +"acorn-walk@npm:^8.1.1": + version: 8.2.0 + resolution: "acorn-walk@npm:8.2.0" + checksum: 10c0/dbe92f5b2452c93e960c5594e666dd1fae141b965ff2cb4a1e1d0381e3e4db4274c5ce4ffa3d681a86ca2a8d4e29d5efc0670a08e23fd2800051ea387df56ca2 + languageName: node + linkType: hard + +"acorn@npm:^8.4.1": + version: 8.8.0 + resolution: "acorn@npm:8.8.0" + bin: + acorn: bin/acorn + checksum: 10c0/5efce4f59554e0ab766f32932cba34b86cc2ecdf24fcd27463beff41d8a1b1b9575c21f92c1b9f7f82b93374a9d5aed33c91f93e2d0cb1bdf3f1e06ec131e816 + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" + dependencies: + debug: "npm:^4.3.4" + checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: "npm:^2.0.0" + indent-string: "npm:^4.0.0" + checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 10c0/cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c + languageName: node + linkType: hard + +"arg@npm:^4.1.0": + version: 4.1.3 + resolution: "arg@npm:4.1.3" + checksum: 10c0/070ff801a9d236a6caa647507bdcc7034530604844d64408149a26b9e87c2f97650055c0f049abd1efc024b334635c01f29e0b632b371ac3f26130f4cf65997a + languageName: node + linkType: hard + +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: 10c0/25456b2aa333250f01143968e02e4884a34588a8538fbbf65c91a637f1dbfb8069249133cd2f4e530f10f624d206a664e7df30207830b659e9f5298b00a4099b + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.4 + resolution: "cacache@npm:18.0.4" + dependencies: + "@npmcli/fs": "npm:^3.1.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^4.0.0" + ssri: "npm:^10.0.0" + tar: "npm:^6.1.11" + unique-filename: "npm:^3.0.0" + checksum: 10c0/6c055bafed9de4f3dcc64ac3dc7dd24e863210902b7c470eb9ce55a806309b3efff78033e3d8b4f7dcc5d467f2db43c6a2857aaaf26f0094b8a351d44c42179f + languageName: node + linkType: hard + +"chai@npm:^4.3.6": + version: 4.3.6 + resolution: "chai@npm:4.3.6" + dependencies: + assertion-error: "npm:^1.1.0" + check-error: "npm:^1.0.2" + deep-eql: "npm:^3.0.1" + get-func-name: "npm:^2.0.0" + loupe: "npm:^2.3.1" + pathval: "npm:^1.1.1" + type-detect: "npm:^4.0.5" + checksum: 10c0/7bcc2e72db775cf94853bf8deb481e47f83705b95bb67b13c32367b2f6913a55e9c24dea0d597027626412b928f28ccd4de7f7608aaeab12a6350c68529148c9 + languageName: node + linkType: hard + +"check-error@npm:^1.0.2": + version: 1.0.2 + resolution: "check-error@npm:1.0.2" + checksum: 10c0/c58ac4d6a92203209a61d025568198c073f101691eb6247f999266e1d1e3ab3af2bbe0a41af5008c1f1b95446ec7831e6ba91f03816177f2da852f316ad7921d + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"create-require@npm:^1.1.0": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 + languageName: node + linkType: hard + +"debug@npm:4": + version: 4.3.5 + resolution: "debug@npm:4.3.5" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/082c375a2bdc4f4469c99f325ff458adad62a3fc2c482d59923c260cb08152f34e2659f72b3767db8bb2f21ca81a60a42d1019605a412132d7b9f59363a005cc + languageName: node + linkType: hard + +"debug@npm:^4.3.4": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 + languageName: node + linkType: hard + +"deep-eql@npm:^3.0.1": + version: 3.0.1 + resolution: "deep-eql@npm:3.0.1" + dependencies: + type-detect: "npm:^4.0.0" + checksum: 10c0/80b33c1c7713b3d5db89e6b5e9b22050f39c8a88e12a015616da8391e013988790d045a5c612b0c6dc43cc4bec51eadbe0fcf6075cc9717f8f56efdb305b6e6f + languageName: node + linkType: hard + +"diff@npm:^4.0.1": + version: 4.0.2 + resolution: "diff@npm:4.0.2" + checksum: 10c0/81b91f9d39c4eaca068eb0c1eb0e4afbdc5bb2941d197f513dd596b820b956fef43485876226d65d497bebc15666aa2aa82c679e84f65d5f2bfbf14ee46e32c1 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"esbuild-android-64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-android-64@npm:0.14.54" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"esbuild-android-arm64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-android-arm64@npm:0.14.54" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"esbuild-darwin-64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-darwin-64@npm:0.14.54" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"esbuild-darwin-arm64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-darwin-arm64@npm:0.14.54" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"esbuild-freebsd-64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-freebsd-64@npm:0.14.54" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"esbuild-freebsd-arm64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-freebsd-arm64@npm:0.14.54" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"esbuild-linux-32@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-linux-32@npm:0.14.54" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"esbuild-linux-64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-linux-64@npm:0.14.54" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"esbuild-linux-arm64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-linux-arm64@npm:0.14.54" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"esbuild-linux-arm@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-linux-arm@npm:0.14.54" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"esbuild-linux-mips64le@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-linux-mips64le@npm:0.14.54" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"esbuild-linux-ppc64le@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-linux-ppc64le@npm:0.14.54" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"esbuild-linux-riscv64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-linux-riscv64@npm:0.14.54" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"esbuild-linux-s390x@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-linux-s390x@npm:0.14.54" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"esbuild-netbsd-64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-netbsd-64@npm:0.14.54" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"esbuild-openbsd-64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-openbsd-64@npm:0.14.54" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"esbuild-sunos-64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-sunos-64@npm:0.14.54" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"esbuild-windows-32@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-windows-32@npm:0.14.54" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"esbuild-windows-64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-windows-64@npm:0.14.54" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"esbuild-windows-arm64@npm:0.14.54": + version: 0.14.54 + resolution: "esbuild-windows-arm64@npm:0.14.54" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"esbuild@npm:^0.14.47": + version: 0.14.54 + resolution: "esbuild@npm:0.14.54" + dependencies: + "@esbuild/linux-loong64": "npm:0.14.54" + esbuild-android-64: "npm:0.14.54" + esbuild-android-arm64: "npm:0.14.54" + esbuild-darwin-64: "npm:0.14.54" + esbuild-darwin-arm64: "npm:0.14.54" + esbuild-freebsd-64: "npm:0.14.54" + esbuild-freebsd-arm64: "npm:0.14.54" + esbuild-linux-32: "npm:0.14.54" + esbuild-linux-64: "npm:0.14.54" + esbuild-linux-arm: "npm:0.14.54" + esbuild-linux-arm64: "npm:0.14.54" + esbuild-linux-mips64le: "npm:0.14.54" + esbuild-linux-ppc64le: "npm:0.14.54" + esbuild-linux-riscv64: "npm:0.14.54" + esbuild-linux-s390x: "npm:0.14.54" + esbuild-netbsd-64: "npm:0.14.54" + esbuild-openbsd-64: "npm:0.14.54" + esbuild-sunos-64: "npm:0.14.54" + esbuild-windows-32: "npm:0.14.54" + esbuild-windows-64: "npm:0.14.54" + esbuild-windows-arm64: "npm:0.14.54" + dependenciesMeta: + "@esbuild/linux-loong64": + optional: true + esbuild-android-64: + optional: true + esbuild-android-arm64: + optional: true + esbuild-darwin-64: + optional: true + esbuild-darwin-arm64: + optional: true + esbuild-freebsd-64: + optional: true + esbuild-freebsd-arm64: + optional: true + esbuild-linux-32: + optional: true + esbuild-linux-64: + optional: true + esbuild-linux-arm: + optional: true + esbuild-linux-arm64: + optional: true + esbuild-linux-mips64le: + optional: true + esbuild-linux-ppc64le: + optional: true + esbuild-linux-riscv64: + optional: true + esbuild-linux-s390x: + optional: true + esbuild-netbsd-64: + optional: true + esbuild-openbsd-64: + optional: true + esbuild-sunos-64: + optional: true + esbuild-windows-32: + optional: true + esbuild-windows-64: + optional: true + esbuild-windows-arm64: + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/1df3cf7c5175ebee284fd027f287385a07ce8a0f0460a4412881aeff707577d91e55302f220ee8397b3b5aa17f4ceeb80eac16f36fc676532ff1b744e5965f2d + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.2.1 + resolution: "foreground-child@npm:3.2.1" + dependencies: + cross-spawn: "npm:^7.0.0" + signal-exit: "npm:^4.0.1" + checksum: 10c0/9a53a33dbd87090e9576bef65fb4a71de60f6863a8062a7b11bc1cbe3cc86d428677d7c0b9ef61cdac11007ac580006f78bd5638618d564cfd5e6fd713d6878f + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fsevents@npm:~2.3.2": + version: 2.3.2 + resolution: "fsevents@npm:2.3.2" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/be78a3efa3e181cda3cf7a4637cb527bcebb0bd0ea0440105a3bb45b86f9245b307dc10a2507e8f4498a7d4ec349d1910f4d73e4d4495b16103106e07eee735b + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": + version: 2.3.2 + resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.1": + version: 1.1.1 + resolution: "function-bind@npm:1.1.1" + checksum: 10c0/60b74b2407e1942e1ed7f8c284f8ef714d0689dcfce5319985a5b7da3fc727f40b4a59ec72dc55aa83365ad7b8fa4fac3a30d93c850a2b452f29ae03dbc10a1e + languageName: node + linkType: hard + +"get-func-name@npm:^2.0.0": + version: 2.0.0 + resolution: "get-func-name@npm:2.0.0" + checksum: 10c0/ed8791f7ba92cfd747259dff7ec8b6cc42734cebd031fb58c99a6e71d24d3532d84b46ad7806cafad6ad21784dd04ae1808a002d2b21001425e21f5f394c34e7 + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + +"graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"has@npm:^1.0.3": + version: 1.0.3 + resolution: "has@npm:1.0.3" + dependencies: + function-bind: "npm:^1.1.1" + checksum: 10c0/e1da0d2bd109f116b632f27782cf23182b42f14972ca9540e4c5aa7e52647407a0a4a76937334fddcb56befe94a3494825ec22b19b51f5e5507c3153fd1a5e1b + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" + dependencies: + agent-base: "npm:^7.0.2" + debug: "npm:4" + checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc + languageName: node + linkType: hard + +"is-core-module@npm:^2.9.0": + version: 2.10.0 + resolution: "is-core-module@npm:2.10.0" + dependencies: + has: "npm:^1.0.3" + checksum: 10c0/af7c3b24cb3375688a84306dcfa71c9305fd03af6548aaeb51ed345f85abafe22e071835b3a5f4bb1e87b434404410ec31ee45749f617a7acf2a4dcb9f677ae7 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 + languageName: node + linkType: hard + +"local-pkg@npm:^0.4.2": + version: 0.4.2 + resolution: "local-pkg@npm:0.4.2" + checksum: 10c0/85f4463d7b29b19cca8c71e0d02c486fb98b5fdb0c1f5ec73e2fb984e9d35119cd88996ac8ef86f9b0d9865785fc4ccdcd1207f76c028cb27b76f398b9bbba2a + languageName: node + linkType: hard + +"loupe@npm:^2.3.1": + version: 2.3.4 + resolution: "loupe@npm:2.3.4" + dependencies: + get-func-name: "npm:^2.0.0" + checksum: 10c0/a48a97f7be1fe0ec28dc53fce366e44b9440b5781b7175727f397c3096b379986dc1d08c5e2b0bc50f34ba2e6836684a6b222e9bc26765c1e97368df80afe459 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb + languageName: node + linkType: hard + +"make-error@npm:^1.1.1": + version: 1.3.6 + resolution: "make-error@npm:1.3.6" + checksum: 10c0/171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" + dependencies: + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" + http-cache-semantics: "npm:^4.1.1" + is-lambda: "npm:^1.0.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^3.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^0.6.3" + proc-log: "npm:^4.2.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^10.0.0" + checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^2.1.2" + dependenciesMeta: + encoding: + optional: true + checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: "npm:^3.0.0" + yallist: "npm:^4.0.0" + checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc + languageName: node + linkType: hard + +"nanoid@npm:^3.3.4": + version: 3.3.4 + resolution: "nanoid@npm:3.3.4" + bin: + nanoid: bin/nanoid.cjs + checksum: 10c0/a0747d5c6021828fe8d38334e5afb05d3268d7d4b06024058ec894ccc47070e4e81d268a6b75488d2ff3485fa79a75c251d4b7c6f31051bb54bb662b6fd2a27d + languageName: node + linkType: hard + +"negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.2.0 + resolution: "node-gyp@npm:10.2.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^4.1.0" + semver: "npm:^7.3.5" + tar: "npm:^6.2.1" + which: "npm:^4.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/00630d67dbd09a45aee0a5d55c05e3916ca9e6d427ee4f7bc392d2d3dc5fad7449b21fc098dd38260a53d9dcc9c879b36704a1994235d4707e7271af7e9a835b + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.1 + resolution: "nopt@npm:7.2.1" + dependencies: + abbrev: "npm:^2.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: "npm:^3.0.0" + checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033 + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: 10c0/f63e1bc1b33593cdf094ed6ff5c49c1c0dc5dc20a646ca9725cc7fe7cd9995002d51d5685b9b2ec6814342935748b711bafa840f84c0bb04e38ff40a335c94dc + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0": + version: 1.0.0 + resolution: "picocolors@npm:1.0.0" + checksum: 10c0/20a5b249e331c14479d94ec6817a182fd7a5680debae82705747b2db7ec50009a5f6648d0621c561b0572703f84dbef0858abcbd5856d3c5511426afcb1961f7 + languageName: node + linkType: hard + +"postcss@npm:^8.4.16": + version: 8.4.16 + resolution: "postcss@npm:8.4.16" + dependencies: + nanoid: "npm:^3.3.4" + picocolors: "npm:^1.0.0" + source-map-js: "npm:^1.0.2" + checksum: 10c0/971e10b5492ffce3d30e39ffba1b4f135d0c751bf774493babe4cb89ddb4995aabb2ce290f48bbf1d9ae60016a6ad492535e614b22b15322f977c7744e800fa2 + languageName: node + linkType: hard + +"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"resolve@npm:^1.22.1": + version: 1.22.1 + resolution: "resolve@npm:1.22.1" + dependencies: + is-core-module: "npm:^2.9.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/6d58b1cb40f3fc80b9e45dd799d84cdc3829a993e4b9fa3b59d331e1dfacd0870e1851f4d0eb549d68c796e0b7087b43d1aec162653ccccff9e18191221a6e7d + languageName: node + linkType: hard + +"resolve@patch:resolve@npm%3A^1.22.1#optional!builtin": + version: 1.22.1 + resolution: "resolve@patch:resolve@npm%3A1.22.1#optional!builtin::version=1.22.1&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.9.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/0d8ccceba5537769c42aa75e4aa75ae854aac866a11d7e9ffdb1663f0158ee646a0d48fc2818ed5e7fb364d64220a1fb9092a160e11e00cbdd5fbab39a13092c + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"rollup@npm:>=2.75.6 <2.77.0 || ~2.77.0": + version: 2.77.3 + resolution: "rollup@npm:2.77.3" + dependencies: + fsevents: "npm:~2.3.2" + dependenciesMeta: + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10c0/7e04ba4e8fdbc3a4a368013e4b788044c16fe94e7301aacbf38e37210983e159b97887ddd3333be9f78fedb30264f094c111ff56a0207c21d4e1745248a7aa42 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"semver@npm:^7.3.5": + version: 7.6.2 + resolution: "semver@npm:7.6.2" + bin: + semver: bin/semver.js + checksum: 10c0/97d3441e97ace8be4b1976433d1c32658f6afaff09f143e52c593bae7eef33de19e3e369c88bd985ce1042c6f441c80c6803078d1de2a9988080b66684cbb30c + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" + dependencies: + agent-base: "npm:^7.1.1" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10c0/345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.3 + resolution: "socks@npm:2.8.3" + dependencies: + ip-address: "npm:^9.0.5" + smart-buffer: "npm:^4.2.0" + checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 + languageName: node + linkType: hard + +"source-map-js@npm:^1.0.2": + version: 1.0.2 + resolution: "source-map-js@npm:1.0.2" + checksum: 10c0/32f2dfd1e9b7168f9a9715eb1b4e21905850f3b50cf02cf476e47e4eebe8e6b762b63a64357896aa29b37e24922b4282df0f492e0d2ace572b43d15525976ff8 + languageName: node + linkType: hard + +"spec@workspace:.": + version: 0.0.0-use.local + resolution: "spec@workspace:." + dependencies: + "@types/node": "npm:^18.0.3" + ts-node: "npm:^10.8.2" + typescript: "npm:^4.7.4" + vite: "npm:^3.0.9" + vitest: "npm:^0.22.1" + languageName: unknown + linkType: soft + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.6 + resolution: "ssri@npm:10.0.6" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.2.1": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + dependencies: + chownr: "npm:^2.0.0" + fs-minipass: "npm:^2.0.0" + minipass: "npm:^5.0.0" + minizlib: "npm:^2.1.1" + mkdirp: "npm:^1.0.3" + yallist: "npm:^4.0.0" + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 + languageName: node + linkType: hard + +"tinypool@npm:^0.2.4": + version: 0.2.4 + resolution: "tinypool@npm:0.2.4" + checksum: 10c0/9d705ef2a623d4a2e263dec3bb292d390d83cd7db65d77a030e0f988866f36584802190ca2bc9083b028dee5c06253c6fb4872d52d0f0a9361d77f63b0be968d + languageName: node + linkType: hard + +"tinyspy@npm:^1.0.2": + version: 1.0.2 + resolution: "tinyspy@npm:1.0.2" + checksum: 10c0/349b574b4f7f359ee7d6c99089ab3148291a94cf3143335f21581df68d183d1582ae703021a02ba376fb98aa0749d76445e5d98acee501f123b04b9da760fea1 + languageName: node + linkType: hard + +"ts-node@npm:^10.8.2": + version: 10.9.1 + resolution: "ts-node@npm:10.9.1" + dependencies: + "@cspotcode/source-map-support": "npm:^0.8.0" + "@tsconfig/node10": "npm:^1.0.7" + "@tsconfig/node12": "npm:^1.0.7" + "@tsconfig/node14": "npm:^1.0.0" + "@tsconfig/node16": "npm:^1.0.2" + acorn: "npm:^8.4.1" + acorn-walk: "npm:^8.1.1" + arg: "npm:^4.1.0" + create-require: "npm:^1.1.0" + diff: "npm:^4.0.1" + make-error: "npm:^1.1.1" + v8-compile-cache-lib: "npm:^3.0.1" + yn: "npm:3.1.1" + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + bin: + ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: 10c0/95187932fb83f3901e22546bd2feeac7d2feb4f412f42ac3a595f049a23e8dcf70516dffb51866391228ea2dbcfaea039e250fb2bb334d48a86ab2b6aea0ae2d + languageName: node + linkType: hard + +"type-detect@npm:^4.0.0, type-detect@npm:^4.0.5": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 10c0/8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd + languageName: node + linkType: hard + +"typescript@npm:^4.7.4": + version: 4.7.4 + resolution: "typescript@npm:4.7.4" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/8c1c4007b6ce5b24c49f0e89173ab9e82687cc6ae54418d1140bb63b82d6598d085ac0f993fe3d3d1fbf87a2c76f1f81d394dc76315bc72c7a9f8561c5d8d205 + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A^4.7.4#optional!builtin": + version: 4.7.4 + resolution: "typescript@patch:typescript@npm%3A4.7.4#optional!builtin::version=4.7.4&hash=65a307" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/2eb6e31b04fabec84a4d07b5d567deb5ef0a2971d89d9adb16895f148f7d8508adfb12074abc2efc6966805d3664e68ab67925060e5b0ebd8da616db4b151906 + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: "npm:^4.0.0" + checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 + languageName: node + linkType: hard + +"v8-compile-cache-lib@npm:^3.0.1": + version: 3.0.1 + resolution: "v8-compile-cache-lib@npm:3.0.1" + checksum: 10c0/bdc36fb8095d3b41df197f5fb6f11e3a26adf4059df3213e3baa93810d8f0cc76f9a74aaefc18b73e91fe7e19154ed6f134eda6fded2e0f1c8d2272ed2d2d391 + languageName: node + linkType: hard + +"vite@npm:^2.9.12 || ^3.0.0-0, vite@npm:^3.0.9": + version: 3.0.9 + resolution: "vite@npm:3.0.9" + dependencies: + esbuild: "npm:^0.14.47" + fsevents: "npm:~2.3.2" + postcss: "npm:^8.4.16" + resolve: "npm:^1.22.1" + rollup: "npm:>=2.75.6 <2.77.0 || ~2.77.0" + peerDependencies: + less: "*" + sass: "*" + stylus: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + less: + optional: true + sass: + optional: true + stylus: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/0e39c11e8befd9ac139ab48ace83125bb4ad0ded14fd7c370290af8c001accbb5e67ce7677d958f5b2ffaf0a38b342ffabf166bc33aa5de32a8510ecb4596be9 + languageName: node + linkType: hard + +"vitest@npm:^0.22.1": + version: 0.22.1 + resolution: "vitest@npm:0.22.1" + dependencies: + "@types/chai": "npm:^4.3.3" + "@types/chai-subset": "npm:^1.3.3" + "@types/node": "npm:*" + chai: "npm:^4.3.6" + debug: "npm:^4.3.4" + local-pkg: "npm:^0.4.2" + tinypool: "npm:^0.2.4" + tinyspy: "npm:^1.0.2" + vite: "npm:^2.9.12 || ^3.0.0-0" + peerDependencies: + "@edge-runtime/vm": "*" + "@vitest/browser": "*" + "@vitest/ui": "*" + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 10c0/944d50ca7368636a20a49c22d3c9e217e5312f3531bee7ae2ec3cf70e06e83fdb79d991cd586bbacce7a2b11e28a27d4d01b6a8665fb7372f6844eeef9ee493b + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"yn@npm:3.1.1": + version: 3.1.1 + resolution: "yn@npm:3.1.1" + checksum: 10c0/0732468dd7622ed8a274f640f191f3eaf1f39d5349a1b72836df484998d7d9807fbea094e2f5486d6b0cd2414aad5775972df0e68f8604db89a239f0f4bf7443 + languageName: node + linkType: hard From 5ac623bb69920939a4215979bdbd330ffcbabb9d Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 15 Jul 2024 19:09:09 +0900 Subject: [PATCH 016/139] feat(adapter): add vitest adapter --- crates/adapter/src/runner/mod.rs | 1 + crates/adapter/src/runner/util.rs | 9 + crates/adapter/src/runner/vitest.rs | 330 ++++++++++++++++++++++++++++ 3 files changed, 340 insertions(+) create mode 100644 crates/adapter/src/runner/vitest.rs diff --git a/crates/adapter/src/runner/mod.rs b/crates/adapter/src/runner/mod.rs index d739aa2..4dfec76 100644 --- a/crates/adapter/src/runner/mod.rs +++ b/crates/adapter/src/runner/mod.rs @@ -2,3 +2,4 @@ pub mod cargo_test; pub mod go; pub mod jest; pub mod util; +pub mod vitest; diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index 5310fa9..20e891e 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -2,9 +2,13 @@ use std::collections::HashMap; use std::path::PathBuf; use std::str::FromStr; +use regex::Regex; use serde::Serialize; use testing_language_server::error::LSError; +// If the character value is greater than the line length it defaults back to the line length. +pub const MAX_CHAR_LENGTH: u32 = 10000; + /// determine if a particular file is the root of workspace based on whether it is in the same directory pub fn detect_workspace_from_file(file_path: PathBuf, file_names: &[String]) -> Option { let parent = file_path.parent(); @@ -62,3 +66,8 @@ where serde_json::to_writer(std::io::stdout(), &value)?; Ok(()) } + +pub fn clean_ansi(input: &str) -> String { + let re = Regex::new(r"\x1B\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]").unwrap(); + re.replace_all(input, "").to_string() +} diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs new file mode 100644 index 0000000..3651b05 --- /dev/null +++ b/crates/adapter/src/runner/vitest.rs @@ -0,0 +1,330 @@ +use std::{ + collections::HashMap, + fs::{self, File}, +}; + +use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; +use serde_json::Value; +use tempfile::tempdir; +use testing_language_server::{ + error::LSError, + spec::{ + DiscoverResult, DiscoverResultItem, RunFileTestResult, RunFileTestResultItem, TestItem, + }, +}; +use tree_sitter::{Point, Query, QueryCursor}; + +use crate::model::Runner; + +use super::util::{clean_ansi, detect_workspaces_from_file_paths, send_stdout, MAX_CHAR_LENGTH}; + +#[derive(Eq, PartialEq, Hash, Debug)] +pub struct VitestRunner; + +fn discover(file_path: &str) -> Result, LSError> { + let mut parser = tree_sitter::Parser::new(); + let mut test_items: Vec = vec![]; + parser + .set_language(&tree_sitter_javascript::language()) + .expect("Error loading Rust grammar"); + let source_code = std::fs::read_to_string(file_path)?; + let tree = parser.parse(&source_code, None).unwrap(); + // from https://github.com/marilari88/neotest-vitest/blob/353364aa05b94b09409cbef21b79c97c5564e2ce/lua/neotest-vitest/init.lua#L101 + let query_string = r#" + ; -- Namespaces -- + ; Matches: `describe('context')` + ((call_expression + function: (identifier) @func_name (#eq? @func_name "describe") + arguments: (arguments (string (string_fragment) @namespace.name) (arrow_function)) + )) @namespace.definition + ; Matches: `describe.only('context')` + ((call_expression + function: (member_expression + object: (identifier) @func_name (#any-of? @func_name "describe") + ) + arguments: (arguments (string (string_fragment) @namespace.name) (arrow_function)) + )) @namespace.definition + ; Matches: `describe.each(['data'])('context')` + ((call_expression + function: (call_expression + function: (member_expression + object: (identifier) @func_name (#any-of? @func_name "describe") + ) + ) + arguments: (arguments (string (string_fragment) @namespace.name) (arrow_function)) + )) @namespace.definition + + ; -- Tests -- + ; Matches: `test('test') / it('test')` + ((call_expression + function: (identifier) @func_name (#any-of? @func_name "it" "test") + arguments: (arguments (string (string_fragment) @test.name) (arrow_function)) + )) @test.definition + ; Matches: `test.only('test') / it.only('test')` + ((call_expression + function: (member_expression + object: (identifier) @func_name (#any-of? @func_name "test" "it") + ) + arguments: (arguments (string (string_fragment) @test.name) (arrow_function)) + )) @test.definition + ; Matches: `test.each(['data'])('test') / it.each(['data'])('test')` + ((call_expression + function: (call_expression + function: (member_expression + object: (identifier) @func_name (#any-of? @func_name "it" "test") + ) + ) + arguments: (arguments (string (string_fragment) @test.name) (arrow_function)) + )) @test.definition +"#; + let query = Query::new(&tree_sitter_javascript::language(), query_string) + .expect("Error creating query"); + + let mut cursor = QueryCursor::new(); + cursor.set_byte_range(tree.root_node().byte_range()); + let source = source_code.as_bytes(); + let matches = cursor.matches(&query, tree.root_node(), source); + for m in matches { + let mut namespace_name = ""; + let mut test_start_position = Point::default(); + let mut test_end_position = Point::default(); + for capture in m.captures { + let capture_name = query.capture_names()[capture.index as usize]; + let value = capture.node.utf8_text(source)?; + let start_position = capture.node.start_position(); + let end_position = capture.node.end_position(); + match capture_name { + "namespace.name" => { + namespace_name = value; + } + "test.definition" => { + test_start_position = start_position; + test_end_position = end_position; + } + "test.name" => { + let test_name = value; + let test_item = TestItem { + id: format!("{}:{}", namespace_name, test_name), + name: test_name.to_string(), + start_position: Range { + start: Position { + line: test_start_position.row as u32, + character: test_start_position.column as u32, + }, + end: Position { + line: test_start_position.row as u32, + character: MAX_CHAR_LENGTH, + }, + }, + end_position: Range { + start: Position { + line: test_end_position.row as u32, + character: 0, + }, + end: Position { + line: test_end_position.row as u32, + character: test_end_position.column as u32, + }, + }, + }; + test_items.push(test_item); + test_start_position = Point::default(); + test_end_position = Point::default(); + } + _ => {} + } + } + } + + Ok(test_items) +} + +fn parse_diagnostics( + test_result: &str, + file_paths: Vec, +) -> Result { + let mut result_map: HashMap> = HashMap::new(); + let json: Value = serde_json::from_str(test_result)?; + let test_results = json["testResults"].as_array().unwrap(); + for test_result in test_results { + let file_path = test_result["name"].as_str().unwrap(); + if !file_paths.iter().any(|path| path.contains(file_path)) { + continue; + } + let assertion_results = test_result["assertionResults"].as_array().unwrap(); + 'assertion: for assertion_result in assertion_results { + let status = assertion_result["status"].as_str().unwrap(); + if status != "failed" { + continue 'assertion; + } + let location = assertion_result["location"].as_object().unwrap(); + let failure_messages = assertion_result["failureMessages"].as_array().unwrap(); + let line = location["line"].as_u64().unwrap() - 1; + failure_messages.iter().for_each(|message| { + let message = clean_ansi(message.as_str().unwrap()); + let diagnostic = Diagnostic { + range: lsp_types::Range { + start: lsp_types::Position { + line: line as u32, + // Line and column number is slightly incorrect. + // ref: + // Bug in json reporter line number? · vitest-dev/vitest · Discussion #5350 + // https://github.com/vitest-dev/vitest/discussions/5350 + // Currently, The row numbers are from the parse result, the column numbers are 0 and MAX_CHAR_LENGTH is hard-coded. + character: 0, + }, + end: lsp_types::Position { + line: line as u32, + character: MAX_CHAR_LENGTH, + }, + }, + message, + severity: Some(DiagnosticSeverity::ERROR), + ..Diagnostic::default() + }; + result_map + .entry(file_path.to_string()) + .or_default() + .push(diagnostic); + }) + } + } + Ok(result_map + .into_iter() + .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) + .collect()) +} + +impl Runner for VitestRunner { + fn disover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + let file_paths = args.file_paths; + let mut discover_results: DiscoverResult = vec![]; + + for file_path in file_paths { + let tests = discover(&file_path)?; + discover_results.push(DiscoverResultItem { + tests, + path: file_path, + }); + } + send_stdout(&discover_results)?; + Ok(()) + } + + fn run_file_test( + &self, + args: testing_language_server::spec::RunFileTestArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let workspace_root = args.workspace; + let tempdir = tempdir().unwrap(); + let tempdir_path = tempdir.path(); + let tempfile_path = tempdir_path.join("vitest.json"); + let tempfile = File::create(&tempfile_path)?; + let tempfile_path = tempfile_path.to_str().unwrap(); + std::process::Command::new("vitest") + .current_dir(&workspace_root) + .args([ + "--watch=false", + "--reporter=json", + "--outputFile=", + tempfile_path, + ]) + .output() + .unwrap(); + let test_result = fs::read_to_string(tempfile_path)?; + let diagnostics: RunFileTestResult = parse_diagnostics(&test_result, file_paths)?; + send_stdout(&diagnostics)?; + drop(tempfile); + let _ = tempdir.close(); + Ok(()) + } + + fn detect_workspaces( + &self, + args: testing_language_server::spec::DetectWorkspaceArgs, + ) -> Result<(), LSError> { + send_stdout(&detect_workspaces_from_file_paths( + &args.file_paths, + &[ + "package.json".to_string(), + "vitest.config.ts".to_string(), + "vitest.config.js".to_string(), + "vite.config.ts".to_string(), + "vite.config.js".to_string(), + "vitest.config.mts".to_string(), + "vitest.config.mjs".to_string(), + "vite.config.mts".to_string(), + "vite.config.mjs".to_string(), + ], + ))?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use lsp_types::{Position, Range}; + + use super::*; + + #[test] + fn test_discover() { + let file_path = "../../test_proj/vitest/basic.test.ts"; + let test_items = discover(file_path).unwrap(); + assert_eq!(test_items.len(), 2); + assert_eq!( + test_items, + vec![ + TestItem { + id: String::from(":pass"), + name: String::from("pass"), + start_position: Range { + start: Position { + line: 4, + character: 2 + }, + end: Position { + line: 4, + character: MAX_CHAR_LENGTH + } + }, + end_position: Range { + start: Position { + line: 6, + character: 0 + }, + end: Position { + line: 6, + character: 4 + } + } + }, + TestItem { + id: String::from(":fail"), + name: String::from("fail"), + start_position: Range { + start: Position { + line: 8, + character: 2 + }, + end: Position { + line: 8, + character: MAX_CHAR_LENGTH + } + }, + end_position: Range { + start: Position { + line: 10, + character: 0 + }, + end: Position { + line: 10, + character: 4 + } + } + } + ] + ) + } +} From 478278412272932635ef783ee304336d2f2a5414 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 15 Jul 2024 19:10:02 +0900 Subject: [PATCH 017/139] refactor(adapter): set diagnostic severity explicitly --- crates/adapter/src/main.rs | 1 + crates/adapter/src/model.rs | 6 ++++++ crates/adapter/src/runner/cargo_test.rs | 6 ++++-- crates/adapter/src/runner/go.rs | 2 ++ crates/adapter/src/runner/jest.rs | 9 +++------ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/crates/adapter/src/main.rs b/crates/adapter/src/main.rs index 0638223..9a70a9e 100644 --- a/crates/adapter/src/main.rs +++ b/crates/adapter/src/main.rs @@ -52,6 +52,7 @@ fn handle(commands: AdapterCommands) -> Result<(), LSError> { fn main() { let _guard = Log::init().expect("Failed to initialize logger"); let args = AdapterCommands::parse(); + tracing::info!("adapter args={:#?}", args); if let Err(error) = handle(args) { io::stderr() .write_all(format!("{:#?}", error).as_bytes()) diff --git a/crates/adapter/src/model.rs b/crates/adapter/src/model.rs index 7302cd9..bbab4c0 100644 --- a/crates/adapter/src/model.rs +++ b/crates/adapter/src/model.rs @@ -1,5 +1,6 @@ use crate::runner::cargo_test::CargoTestRunner; use crate::runner::go::GoTestRunner; +use crate::runner::vitest::VitestRunner; use std::str::FromStr; use testing_language_server::error::LSError; use testing_language_server::spec::DetectWorkspaceArgs; @@ -12,6 +13,7 @@ use crate::runner::jest::JestRunner; pub enum AvailableTestKind { CargoTest(CargoTestRunner), Jest(JestRunner), + Vitest(VitestRunner), GoTest(GoTestRunner), } impl Runner for AvailableTestKind { @@ -20,6 +22,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::CargoTest(runner) => runner.disover(args), AvailableTestKind::Jest(runner) => runner.disover(args), AvailableTestKind::GoTest(runner) => runner.disover(args), + AvailableTestKind::Vitest(runner) => runner.disover(args), } } @@ -28,6 +31,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::CargoTest(runner) => runner.run_file_test(args), AvailableTestKind::Jest(runner) => runner.run_file_test(args), AvailableTestKind::GoTest(runner) => runner.run_file_test(args), + AvailableTestKind::Vitest(runner) => runner.run_file_test(args), } } @@ -36,6 +40,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::CargoTest(runner) => runner.detect_workspaces(args), AvailableTestKind::Jest(runner) => runner.detect_workspaces(args), AvailableTestKind::GoTest(runner) => runner.detect_workspaces(args), + AvailableTestKind::Vitest(runner) => runner.detect_workspaces(args), } } } @@ -48,6 +53,7 @@ impl FromStr for AvailableTestKind { "cargo-test" => Ok(AvailableTestKind::CargoTest(CargoTestRunner)), "jest" => Ok(AvailableTestKind::Jest(JestRunner)), "go-test" => Ok(AvailableTestKind::GoTest(GoTestRunner)), + "vitest" => Ok(AvailableTestKind::Vitest(VitestRunner)), _ => Err(anyhow::anyhow!("Unknown test kind: {}", s)), } } diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index d6cc9b4..bf6fde4 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -1,4 +1,5 @@ use crate::runner::util::send_stdout; +use lsp_types::DiagnosticSeverity; use std::collections::HashMap; use std::path::PathBuf; use std::process::Output; @@ -62,6 +63,7 @@ fn parse_diagnostics( }, }, message, + severity: Some(DiagnosticSeverity::ERROR), ..Diagnostic::default() }; result_map @@ -339,7 +341,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace let workspaces = detect_workspaces(&file_paths); assert_eq!(workspaces.len(), 2); - assert!(workspaces.contains_key(&absolute_path_of_test_proj.to_str().unwrap().to_string())); - assert!(workspaces.contains_key(¤t_dir.to_str().unwrap().to_string())); + assert!(workspaces.contains_key(absolute_path_of_test_proj.to_str().unwrap())); + assert!(workspaces.contains_key(current_dir.to_str().unwrap())); } } diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index c765449..652059e 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -2,6 +2,7 @@ use crate::model::Runner; use crate::runner::util::send_stdout; use anyhow::anyhow; use lsp_types::Diagnostic; +use lsp_types::DiagnosticSeverity; use lsp_types::Position; use lsp_types::Range; use regex::Regex; @@ -116,6 +117,7 @@ fn parse_diagnostics( }, }, message: message.clone(), + severity: Some(DiagnosticSeverity::ERROR), ..Diagnostic::default() }; let file_path = workspace_root diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 700dde3..9a7d26b 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -1,8 +1,8 @@ use crate::runner::util::send_stdout; use lsp_types::Diagnostic; +use lsp_types::DiagnosticSeverity; use lsp_types::Position; use lsp_types::Range; -use regex::Regex; use serde_json::Value; use std::collections::HashMap; use std::fs; @@ -21,16 +21,12 @@ use tree_sitter::QueryCursor; use crate::model::Runner; +use super::util::clean_ansi; use super::util::detect_workspaces_from_file_paths; // If the character value is greater than the line length it defaults back to the line length. const MAX_CHAR_LENGTH: u32 = 10000; -fn clean_ansi(input: &str) -> String { - let re = Regex::new(r"\x1B\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]").unwrap(); - re.replace_all(input, "").to_string() -} - fn parse_diagnostics( test_result: &str, file_paths: Vec, @@ -67,6 +63,7 @@ fn parse_diagnostics( }, }, message, + severity: Some(DiagnosticSeverity::ERROR), ..Diagnostic::default() }; result_map From 1d6dd6623e843cdbef355f0713d8e47fe07e2a61 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 15 Jul 2024 19:13:19 +0900 Subject: [PATCH 018/139] refactor: rename directory --- .vim/coc-settings.json | 2 +- Cargo.toml | 2 +- crates/adapter/src/runner/cargo_test.rs | 10 ++-- crates/adapter/src/runner/go.rs | 2 +- crates/adapter/src/runner/jest.rs | 16 +++---- crates/adapter/src/runner/vitest.rs | 2 +- {test_proj => demo}/.vim/coc-settings.json | 0 {test_proj => demo}/go/README.md | 0 {test_proj => demo}/go/cases.go | 0 {test_proj => demo}/go/cases_test.go | 0 {test_proj => demo}/go/example.go | 0 {test_proj => demo}/go/example_test.go | 0 {test_proj => demo}/go/go.mod | 0 {test_proj => demo}/go/go.sum | 0 {test_proj => demo}/go/main.go | 0 {test_proj => demo}/go/main_tagged_test.go | 0 {test_proj => demo}/go/main_test.go | 0 {test_proj => demo}/go/many_table_test.go | 0 {test_proj => demo}/go/map_table_test.go | 0 {test_proj => demo}/go/suite_test.go | 0 .../go/three_level_nested_test.go | 0 {test_proj => demo}/jest/.gitignore | 0 {test_proj => demo}/jest/README.md | 2 +- {test_proj => demo}/jest/another.spec.js | 0 {test_proj => demo}/jest/bun.lockb | Bin {test_proj => demo}/jest/index.js | 0 {test_proj => demo}/jest/index.spec.js | 0 {test_proj => demo}/jest/jsconfig.json | 0 {test_proj => demo}/jest/output.json | 20 +++----- {test_proj => demo}/jest/package.json | 4 +- {test_proj => demo}/rust/.gitignore | 0 {test_proj => demo}/rust/Cargo.lock | 14 +++--- {test_proj => demo}/rust/Cargo.toml | 2 +- {test_proj => demo}/rust/src/lib.rs | 0 {test_proj => demo}/vitest/.gitignore | 0 {test_proj => demo}/vitest/.yarnrc.yml | 0 {test_proj => demo}/vitest/basic.test.ts | 0 {test_proj => demo}/vitest/package.json | 0 {test_proj => demo}/vitest/vite.config.ts | 0 {test_proj => demo}/vitest/yarn.lock | 0 src/server.rs | 45 ++++++++---------- 41 files changed, 54 insertions(+), 67 deletions(-) rename {test_proj => demo}/.vim/coc-settings.json (100%) rename {test_proj => demo}/go/README.md (100%) rename {test_proj => demo}/go/cases.go (100%) rename {test_proj => demo}/go/cases_test.go (100%) rename {test_proj => demo}/go/example.go (100%) rename {test_proj => demo}/go/example_test.go (100%) rename {test_proj => demo}/go/go.mod (100%) rename {test_proj => demo}/go/go.sum (100%) rename {test_proj => demo}/go/main.go (100%) rename {test_proj => demo}/go/main_tagged_test.go (100%) rename {test_proj => demo}/go/main_test.go (100%) rename {test_proj => demo}/go/many_table_test.go (100%) rename {test_proj => demo}/go/map_table_test.go (100%) rename {test_proj => demo}/go/suite_test.go (100%) rename {test_proj => demo}/go/three_level_nested_test.go (100%) rename {test_proj => demo}/jest/.gitignore (100%) rename {test_proj => demo}/jest/README.md (94%) rename {test_proj => demo}/jest/another.spec.js (100%) rename {test_proj => demo}/jest/bun.lockb (100%) rename {test_proj => demo}/jest/index.js (100%) rename {test_proj => demo}/jest/index.spec.js (100%) rename {test_proj => demo}/jest/jsconfig.json (100%) rename {test_proj => demo}/jest/output.json (67%) rename {test_proj => demo}/jest/package.json (89%) rename {test_proj => demo}/rust/.gitignore (100%) rename {test_proj => demo}/rust/Cargo.lock (99%) rename {test_proj => demo}/rust/Cargo.toml (91%) rename {test_proj => demo}/rust/src/lib.rs (100%) rename {test_proj => demo}/vitest/.gitignore (100%) rename {test_proj => demo}/vitest/.yarnrc.yml (100%) rename {test_proj => demo}/vitest/basic.test.ts (100%) rename {test_proj => demo}/vitest/package.json (100%) rename {test_proj => demo}/vitest/vite.config.ts (100%) rename {test_proj => demo}/vitest/yarn.lock (100%) diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json index f66ce6e..d930726 100644 --- a/.vim/coc-settings.json +++ b/.vim/coc-settings.json @@ -7,7 +7,7 @@ "path": "testing-ls-adapter", "extra_args": ["--test-kind=cargo-test", "--workspace"], "include_patterns": ["/**/*.rs"], - "exclude_patterns": ["/test_proj/**/*"], + "exclude_patterns": ["/demo/**/*"], "workspace_dir": "." } ] diff --git a/Cargo.toml b/Cargo.toml index 2ef64bb..47aadd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT" [workspace] members = [ "crates/adapter"] -exclude = ["test_proj"] +exclude = ["demo"] [[bin]] name = "testing-language-server" diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index bf6fde4..2bd8c3b 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -323,7 +323,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace #[test] fn test_discover() { - let file_path = "../../test_proj/rust/src/lib.rs"; + let file_path = "../../demo/rust/src/lib.rs"; discover(file_path).unwrap(); } @@ -332,16 +332,16 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace let current_dir = std::env::current_dir().unwrap(); let librs = current_dir.join("src/lib.rs"); let mainrs = current_dir.join("src/main.rs"); - let absolute_path_of_test_proj = current_dir.join("../../test_proj/rust"); - let test_proj_librs = absolute_path_of_test_proj.join("src/lib.rs"); - let file_paths: Vec = [librs, mainrs, test_proj_librs] + let absolute_path_of_demo = current_dir.join("../../demo/rust"); + let demo_librs = absolute_path_of_demo.join("src/lib.rs"); + let file_paths: Vec = [librs, mainrs, demo_librs] .iter() .map(|file_path| file_path.to_str().unwrap().to_string()) .collect(); let workspaces = detect_workspaces(&file_paths); assert_eq!(workspaces.len(), 2); - assert!(workspaces.contains_key(absolute_path_of_test_proj.to_str().unwrap())); + assert!(workspaces.contains_key(absolute_path_of_demo.to_str().unwrap())); assert!(workspaces.contains_key(current_dir.to_str().unwrap())); } } diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 652059e..2034709 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -381,7 +381,7 @@ mod tests { #[test] fn test_discover() { - let file_path = "../../test_proj/go/cases_test.go"; + let file_path = "../../demo/go/cases_test.go"; let test_items = discover(file_path).unwrap(); assert!(!test_items.is_empty()); } diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 9a7d26b..541212e 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -289,13 +289,13 @@ mod tests { fn test_parse_diagnostics() { let test_result = std::env::current_dir() .unwrap() - .join("../../test_proj/jest/output.json"); + .join("../../demo/jest/output.json"); let test_result = std::fs::read_to_string(test_result).unwrap(); let diagnostics = parse_diagnostics( &test_result, vec![ - "/absolute_path/test_proj/jest/index.spec.js".to_string(), - "/absolute_path/test_proj/jest/another.spec.js".to_string(), + "/absolute_path/demo/jest/index.spec.js".to_string(), + "/absolute_path/demo/jest/another.spec.js".to_string(), ], ) .unwrap(); @@ -305,22 +305,22 @@ mod tests { #[test] fn test_detect_workspace() { let current_dir = std::env::current_dir().unwrap(); - let absolute_path_of_test_proj = current_dir.join("../../test_proj/jest"); - let test_proj_indexjs = absolute_path_of_test_proj.join("index.spec.js"); - let file_paths: Vec = [test_proj_indexjs] + let absolute_path_of_demo = current_dir.join("../../demo/jest"); + let demo_indexjs = absolute_path_of_demo.join("index.spec.js"); + let file_paths: Vec = [demo_indexjs] .iter() .map(|file_path| file_path.to_str().unwrap().to_string()) .collect(); let detect_result = detect_workspaces(file_paths); assert_eq!(detect_result.len(), 1); detect_result.iter().for_each(|(workspace, _)| { - assert_eq!(workspace, absolute_path_of_test_proj.to_str().unwrap()); + assert_eq!(workspace, absolute_path_of_demo.to_str().unwrap()); }); } #[test] fn test_discover() { - let file_path = "../../test_proj/jest/index.spec.js"; + let file_path = "../../demo/jest/index.spec.js"; let test_items = discover(file_path).unwrap(); assert_eq!(test_items.len(), 1); assert_eq!( diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 3651b05..34549f0 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -270,7 +270,7 @@ mod tests { #[test] fn test_discover() { - let file_path = "../../test_proj/vitest/basic.test.ts"; + let file_path = "../../demo/vitest/basic.test.ts"; let test_items = discover(file_path).unwrap(); assert_eq!(test_items.len(), 2); assert_eq!( diff --git a/test_proj/.vim/coc-settings.json b/demo/.vim/coc-settings.json similarity index 100% rename from test_proj/.vim/coc-settings.json rename to demo/.vim/coc-settings.json diff --git a/test_proj/go/README.md b/demo/go/README.md similarity index 100% rename from test_proj/go/README.md rename to demo/go/README.md diff --git a/test_proj/go/cases.go b/demo/go/cases.go similarity index 100% rename from test_proj/go/cases.go rename to demo/go/cases.go diff --git a/test_proj/go/cases_test.go b/demo/go/cases_test.go similarity index 100% rename from test_proj/go/cases_test.go rename to demo/go/cases_test.go diff --git a/test_proj/go/example.go b/demo/go/example.go similarity index 100% rename from test_proj/go/example.go rename to demo/go/example.go diff --git a/test_proj/go/example_test.go b/demo/go/example_test.go similarity index 100% rename from test_proj/go/example_test.go rename to demo/go/example_test.go diff --git a/test_proj/go/go.mod b/demo/go/go.mod similarity index 100% rename from test_proj/go/go.mod rename to demo/go/go.mod diff --git a/test_proj/go/go.sum b/demo/go/go.sum similarity index 100% rename from test_proj/go/go.sum rename to demo/go/go.sum diff --git a/test_proj/go/main.go b/demo/go/main.go similarity index 100% rename from test_proj/go/main.go rename to demo/go/main.go diff --git a/test_proj/go/main_tagged_test.go b/demo/go/main_tagged_test.go similarity index 100% rename from test_proj/go/main_tagged_test.go rename to demo/go/main_tagged_test.go diff --git a/test_proj/go/main_test.go b/demo/go/main_test.go similarity index 100% rename from test_proj/go/main_test.go rename to demo/go/main_test.go diff --git a/test_proj/go/many_table_test.go b/demo/go/many_table_test.go similarity index 100% rename from test_proj/go/many_table_test.go rename to demo/go/many_table_test.go diff --git a/test_proj/go/map_table_test.go b/demo/go/map_table_test.go similarity index 100% rename from test_proj/go/map_table_test.go rename to demo/go/map_table_test.go diff --git a/test_proj/go/suite_test.go b/demo/go/suite_test.go similarity index 100% rename from test_proj/go/suite_test.go rename to demo/go/suite_test.go diff --git a/test_proj/go/three_level_nested_test.go b/demo/go/three_level_nested_test.go similarity index 100% rename from test_proj/go/three_level_nested_test.go rename to demo/go/three_level_nested_test.go diff --git a/test_proj/jest/.gitignore b/demo/jest/.gitignore similarity index 100% rename from test_proj/jest/.gitignore rename to demo/jest/.gitignore diff --git a/test_proj/jest/README.md b/demo/jest/README.md similarity index 94% rename from test_proj/jest/README.md rename to demo/jest/README.md index 2b2eca2..0771f53 100644 --- a/test_proj/jest/README.md +++ b/demo/jest/README.md @@ -1,4 +1,4 @@ -# test_proj +# demo To install dependencies: diff --git a/test_proj/jest/another.spec.js b/demo/jest/another.spec.js similarity index 100% rename from test_proj/jest/another.spec.js rename to demo/jest/another.spec.js diff --git a/test_proj/jest/bun.lockb b/demo/jest/bun.lockb similarity index 100% rename from test_proj/jest/bun.lockb rename to demo/jest/bun.lockb diff --git a/test_proj/jest/index.js b/demo/jest/index.js similarity index 100% rename from test_proj/jest/index.js rename to demo/jest/index.js diff --git a/test_proj/jest/index.spec.js b/demo/jest/index.spec.js similarity index 100% rename from test_proj/jest/index.spec.js rename to demo/jest/index.spec.js diff --git a/test_proj/jest/jsconfig.json b/demo/jest/jsconfig.json similarity index 100% rename from test_proj/jest/jsconfig.json rename to demo/jest/jsconfig.json diff --git a/test_proj/jest/output.json b/demo/jest/output.json similarity index 67% rename from test_proj/jest/output.json rename to demo/jest/output.json index b7379e9..cd52c72 100644 --- a/test_proj/jest/output.json +++ b/demo/jest/output.json @@ -32,9 +32,7 @@ { "assertionResults": [ { - "ancestorTitles": [ - "index" - ], + "ancestorTitles": ["index"], "duration": 3, "failureDetails": [ { @@ -48,7 +46,7 @@ } ], "failureMessages": [ - "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m0\u001b[39m\nReceived: \u001b[31m1\u001b[39m\n at Object.toBe (/absolute_path/test_proj/jest/index.spec.js:4:15)\n at Promise.then.completed (/absolute_path/test_proj/jest/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/absolute_path/test_proj/jest/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:121:9)\n at run (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/absolute_path/test_proj/jest/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/absolute_path/test_proj/jest/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/absolute_path/test_proj/jest/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/absolute_path/test_proj/jest/node_modules/jest-runner/build/runTest.js:444:34)" + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m0\u001b[39m\nReceived: \u001b[31m1\u001b[39m\n at Object.toBe (/absolute_path/demo/jest/index.spec.js:4:15)\n at Promise.then.completed (/absolute_path/demo/jest/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/absolute_path/demo/jest/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:121:9)\n at run (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/absolute_path/demo/jest/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/absolute_path/demo/jest/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/absolute_path/demo/jest/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/absolute_path/demo/jest/node_modules/jest-runner/build/runTest.js:444:34)" ], "fullName": "index fail", "invocations": 1, @@ -64,7 +62,7 @@ ], "endTime": 1714484637874, "message": "\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1mindex › fail\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\n Expected: \u001b[32m0\u001b[39m\n Received: \u001b[31m1\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 2 |\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 3 |\u001b[39m it(\u001b[32m\"fail\"\u001b[39m\u001b[33m,\u001b[39m () \u001b[33m=>\u001b[39m {\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 4 |\u001b[39m expect(\u001b[35m1\u001b[39m)\u001b[33m.\u001b[39mtoBe(\u001b[35m0\u001b[39m)\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 5 |\u001b[39m })\u001b[22m\n\u001b[2m \u001b[90m 6 |\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 7 |\u001b[39m })\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object.toBe (\u001b[22m\u001b[2m\u001b[0m\u001b[36mindex.spec.js\u001b[39m\u001b[0m\u001b[2m:4:15)\u001b[22m\u001b[2m\u001b[22m\n", - "name": "/absolute_path/test_proj/jest/index.spec.js", + "name": "/absolute_path/demo/jest/index.spec.js", "startTime": 1714484637684, "status": "failed", "summary": "" @@ -72,9 +70,7 @@ { "assertionResults": [ { - "ancestorTitles": [ - "another" - ], + "ancestorTitles": ["another"], "duration": 2, "failureDetails": [ { @@ -88,7 +84,7 @@ } ], "failureMessages": [ - "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m0\u001b[39m\nReceived: \u001b[31m1\u001b[39m\n at Object.toBe (/absolute_path/test_proj/jest/another.spec.js:4:15)\n at Promise.then.completed (/absolute_path/test_proj/jest/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/absolute_path/test_proj/jest/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:121:9)\n at run (/absolute_path/test_proj/jest/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/absolute_path/test_proj/jest/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/absolute_path/test_proj/jest/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/absolute_path/test_proj/jest/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/absolute_path/test_proj/jest/node_modules/jest-runner/build/runTest.js:444:34)" + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m0\u001b[39m\nReceived: \u001b[31m1\u001b[39m\n at Object.toBe (/absolute_path/demo/jest/another.spec.js:4:15)\n at Promise.then.completed (/absolute_path/demo/jest/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/absolute_path/demo/jest/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:316:40)\n at _runTest (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:121:9)\n at run (/absolute_path/demo/jest/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/absolute_path/demo/jest/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/absolute_path/demo/jest/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/absolute_path/demo/jest/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/absolute_path/demo/jest/node_modules/jest-runner/build/runTest.js:444:34)" ], "fullName": "another fail", "invocations": 1, @@ -102,9 +98,7 @@ "title": "fail" }, { - "ancestorTitles": [ - "another" - ], + "ancestorTitles": ["another"], "duration": 1, "failureDetails": [], "failureMessages": [], @@ -122,7 +116,7 @@ ], "endTime": 1714484637974, "message": "\u001b[1m\u001b[31m \u001b[1m● \u001b[22m\u001b[1manother › fail\u001b[39m\u001b[22m\n\n \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\n Expected: \u001b[32m0\u001b[39m\n Received: \u001b[31m1\u001b[39m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[0m \u001b[90m 2 |\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 3 |\u001b[39m it(\u001b[32m\"fail\"\u001b[39m\u001b[33m,\u001b[39m () \u001b[33m=>\u001b[39m {\u001b[22m\n\u001b[2m \u001b[31m\u001b[1m>\u001b[22m\u001b[2m\u001b[39m\u001b[90m 4 |\u001b[39m expect(\u001b[35m1\u001b[39m)\u001b[33m.\u001b[39mtoBe(\u001b[35m0\u001b[39m)\u001b[22m\n\u001b[2m \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[2m\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 5 |\u001b[39m })\u001b[22m\n\u001b[2m \u001b[90m 6 |\u001b[39m\u001b[22m\n\u001b[2m \u001b[90m 7 |\u001b[39m it(\u001b[32m\"pass\"\u001b[39m\u001b[33m,\u001b[39m () \u001b[33m=>\u001b[39m {\u001b[0m\u001b[22m\n\u001b[2m\u001b[22m\n\u001b[2m \u001b[2mat Object.toBe (\u001b[22m\u001b[2m\u001b[0m\u001b[36manother.spec.js\u001b[39m\u001b[0m\u001b[2m:4:15)\u001b[22m\u001b[2m\u001b[22m\n", - "name": "/absolute_path/test_proj/jest/another.spec.js", + "name": "/absolute_path/demo/jest/another.spec.js", "startTime": 1714484637879, "status": "failed", "summary": "" diff --git a/test_proj/jest/package.json b/demo/jest/package.json similarity index 89% rename from test_proj/jest/package.json rename to demo/jest/package.json index b4719dc..0dcfcbd 100644 --- a/test_proj/jest/package.json +++ b/demo/jest/package.json @@ -1,5 +1,5 @@ { - "name": "test_proj", + "name": "demo", "module": "index.js", "type": "module", "devDependencies": { @@ -10,4 +10,4 @@ "peerDependencies": { "typescript": "^5.0.0" } -} \ No newline at end of file +} diff --git a/test_proj/rust/.gitignore b/demo/rust/.gitignore similarity index 100% rename from test_proj/rust/.gitignore rename to demo/rust/.gitignore diff --git a/test_proj/rust/Cargo.lock b/demo/rust/Cargo.lock similarity index 99% rename from test_proj/rust/Cargo.lock rename to demo/rust/Cargo.lock index cef7872..531608a 100644 --- a/test_proj/rust/Cargo.lock +++ b/demo/rust/Cargo.lock @@ -62,6 +62,13 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "demo" +version = "0.1.0" +dependencies = [ + "tokio", +] + [[package]] name = "gimli" version = "0.28.1" @@ -239,13 +246,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "test_proj" -version = "0.1.0" -dependencies = [ - "tokio", -] - [[package]] name = "tokio" version = "1.37.0" diff --git a/test_proj/rust/Cargo.toml b/demo/rust/Cargo.toml similarity index 91% rename from test_proj/rust/Cargo.toml rename to demo/rust/Cargo.toml index b06b397..dccb943 100644 --- a/test_proj/rust/Cargo.toml +++ b/demo/rust/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "test_proj" +name = "demo" version = "0.1.0" edition = "2021" diff --git a/test_proj/rust/src/lib.rs b/demo/rust/src/lib.rs similarity index 100% rename from test_proj/rust/src/lib.rs rename to demo/rust/src/lib.rs diff --git a/test_proj/vitest/.gitignore b/demo/vitest/.gitignore similarity index 100% rename from test_proj/vitest/.gitignore rename to demo/vitest/.gitignore diff --git a/test_proj/vitest/.yarnrc.yml b/demo/vitest/.yarnrc.yml similarity index 100% rename from test_proj/vitest/.yarnrc.yml rename to demo/vitest/.yarnrc.yml diff --git a/test_proj/vitest/basic.test.ts b/demo/vitest/basic.test.ts similarity index 100% rename from test_proj/vitest/basic.test.ts rename to demo/vitest/basic.test.ts diff --git a/test_proj/vitest/package.json b/demo/vitest/package.json similarity index 100% rename from test_proj/vitest/package.json rename to demo/vitest/package.json diff --git a/test_proj/vitest/vite.config.ts b/demo/vitest/vite.config.ts similarity index 100% rename from test_proj/vitest/vite.config.ts rename to demo/vitest/vite.config.ts diff --git a/test_proj/vitest/yarn.lock b/demo/vitest/yarn.lock similarity index 100% rename from test_proj/vitest/yarn.lock rename to demo/vitest/yarn.lock diff --git a/src/server.rs b/src/server.rs index 63111e1..7e9ea27 100644 --- a/src/server.rs +++ b/src/server.rs @@ -577,12 +577,12 @@ mod tests { #[test] fn test_check_file() { - let abs_path_of_test_proj = std::env::current_dir().unwrap().join("test_proj/rust"); + let abs_path_of_demo = std::env::current_dir().unwrap().join("demo/rust"); let mut server = TestingLS { initialize_params: InitializeParams { workspace_folders: Some(vec![WorkspaceFolder { - uri: Url::from_file_path(&abs_path_of_test_proj).unwrap(), - name: "test_proj".to_string(), + uri: Url::from_file_path(&abs_path_of_demo).unwrap(), + name: "demo".to_string(), }]), ..InitializeParams::default() }, @@ -591,13 +591,13 @@ mod tests { }, workspaces_cache: Vec::new(), }; - let librs = abs_path_of_test_proj.join("lib.rs"); + let librs = abs_path_of_demo.join("lib.rs"); server.check_file(librs.to_str().unwrap(), true).unwrap(); } #[test] fn test_check_workspace() { - let abs_path_of_test_proj = std::env::current_dir().unwrap().join("test_proj/rust"); + let abs_path_of_demo = std::env::current_dir().unwrap().join("demo/rust"); let abs_path_of_rust_adapter = std::env::current_dir() .unwrap() .join("target/debug/testing-ls-adapter"); @@ -613,8 +613,8 @@ mod tests { let mut server = TestingLS { initialize_params: InitializeParams { workspace_folders: Some(vec![WorkspaceFolder { - uri: Url::from_file_path(abs_path_of_test_proj.clone()).unwrap(), - name: "test_proj".to_string(), + uri: Url::from_file_path(abs_path_of_demo.clone()).unwrap(), + name: "demo".to_string(), }]), ..InitializeParams::default() }, @@ -634,7 +634,7 @@ mod tests { .workspaces .iter() .for_each(|(workspace, paths)| { - assert_eq!(workspace, abs_path_of_test_proj.to_str().unwrap()); + assert_eq!(workspace, abs_path_of_demo.to_str().unwrap()); paths.iter().for_each(|path| { assert!(path.contains("rust/src")); }); @@ -644,20 +644,20 @@ mod tests { #[test] fn project_files_are_filtered_by_extension() { - let absolute_path_of_test_proj = std::env::current_dir().unwrap().join("test_proj"); + let absolute_path_of_demo = std::env::current_dir().unwrap().join("demo"); let files = TestingLS::project_files( - &absolute_path_of_test_proj.clone(), + &absolute_path_of_demo.clone(), &["/rust/src/lib.rs".to_string()], &["/rust/target/**/*".to_string()], ); - let librs = absolute_path_of_test_proj.join("rust/src/lib.rs"); + let librs = absolute_path_of_demo.join("rust/src/lib.rs"); assert_eq!(files, vec![librs.to_str().unwrap()]); let files = TestingLS::project_files( - &absolute_path_of_test_proj.clone(), + &absolute_path_of_demo.clone(), &["jest/*.spec.js".to_string()], &["jest/another.spec.js".to_string()], ); - let test_file = absolute_path_of_test_proj.join("jest/index.spec.js"); + let test_file = absolute_path_of_demo.join("jest/index.spec.js"); assert_eq!(files, vec![test_file.to_str().unwrap()]); } @@ -673,18 +673,15 @@ mod tests { extra_args: vec!["--invalid-arg".to_string()], ..Default::default() }; - let abs_path_of_test_proj = std::env::current_dir().unwrap().join("test_proj/rust"); - let files = TestingLS::project_files( - &abs_path_of_test_proj.clone(), - &["/**/*.rs".to_string()], - &[], - ); + let abs_path_of_demo = std::env::current_dir().unwrap().join("demo/rust"); + let files = + TestingLS::project_files(&abs_path_of_demo.clone(), &["/**/*.rs".to_string()], &[]); let server = TestingLS { initialize_params: InitializeParams { workspace_folders: Some(vec![WorkspaceFolder { - uri: Url::from_file_path(&abs_path_of_test_proj).unwrap(), - name: "test_proj".to_string(), + uri: Url::from_file_path(&abs_path_of_demo).unwrap(), + name: "demo".to_string(), }]), ..InitializeParams::default() }, @@ -694,11 +691,7 @@ mod tests { workspaces_cache: Vec::new(), }; let diagnostics = server - .get_diagnostics( - &adapter_conf, - abs_path_of_test_proj.to_str().unwrap(), - &files, - ) + .get_diagnostics(&adapter_conf, abs_path_of_demo.to_str().unwrap(), &files) .unwrap(); assert_eq!(diagnostics.len(), 1); let diagnostic = diagnostics.first().unwrap().1.first().unwrap(); From f78cf7f888e6b18fa319d7753c4cb558a3607328 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 15 Jul 2024 19:14:27 +0900 Subject: [PATCH 019/139] test(adapter): fix failed test --- crates/adapter/src/runner/cargo_test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 2bd8c3b..1327022 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -315,6 +315,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace } }, message: message.to_string(), + severity: Some(DiagnosticSeverity::ERROR), ..Diagnostic::default() }] }] From b887d653a29fd94a4601c6c1578000a8ff2f1275 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 16 Jul 2024 00:22:36 +0900 Subject: [PATCH 020/139] feat(adapter): add adapter for cargo-nextest close #18 --- crates/adapter/src/model.rs | 6 + crates/adapter/src/runner/cargo_nextest.rs | 197 +++++++++++++++++++++ crates/adapter/src/runner/cargo_test.rs | 180 ++----------------- crates/adapter/src/runner/mod.rs | 1 + crates/adapter/src/runner/util.rs | 168 +++++++++++++++++- demo/.vim/coc-settings.json | 12 +- 6 files changed, 392 insertions(+), 172 deletions(-) create mode 100644 crates/adapter/src/runner/cargo_nextest.rs diff --git a/crates/adapter/src/model.rs b/crates/adapter/src/model.rs index bbab4c0..1169838 100644 --- a/crates/adapter/src/model.rs +++ b/crates/adapter/src/model.rs @@ -1,3 +1,4 @@ +use crate::runner::cargo_nextest::CargoNextestRunner; use crate::runner::cargo_test::CargoTestRunner; use crate::runner::go::GoTestRunner; use crate::runner::vitest::VitestRunner; @@ -12,6 +13,7 @@ use crate::runner::jest::JestRunner; #[derive(Debug, Eq, PartialEq)] pub enum AvailableTestKind { CargoTest(CargoTestRunner), + CargoNextest(CargoNextestRunner), Jest(JestRunner), Vitest(VitestRunner), GoTest(GoTestRunner), @@ -20,6 +22,7 @@ impl Runner for AvailableTestKind { fn disover(&self, args: DiscoverArgs) -> Result<(), LSError> { match self { AvailableTestKind::CargoTest(runner) => runner.disover(args), + AvailableTestKind::CargoNextest(runner) => runner.disover(args), AvailableTestKind::Jest(runner) => runner.disover(args), AvailableTestKind::GoTest(runner) => runner.disover(args), AvailableTestKind::Vitest(runner) => runner.disover(args), @@ -29,6 +32,7 @@ impl Runner for AvailableTestKind { fn run_file_test(&self, args: RunFileTestArgs) -> Result<(), LSError> { match self { AvailableTestKind::CargoTest(runner) => runner.run_file_test(args), + AvailableTestKind::CargoNextest(runner) => runner.run_file_test(args), AvailableTestKind::Jest(runner) => runner.run_file_test(args), AvailableTestKind::GoTest(runner) => runner.run_file_test(args), AvailableTestKind::Vitest(runner) => runner.run_file_test(args), @@ -38,6 +42,7 @@ impl Runner for AvailableTestKind { fn detect_workspaces(&self, args: DetectWorkspaceArgs) -> Result<(), LSError> { match self { AvailableTestKind::CargoTest(runner) => runner.detect_workspaces(args), + AvailableTestKind::CargoNextest(runner) => runner.detect_workspaces(args), AvailableTestKind::Jest(runner) => runner.detect_workspaces(args), AvailableTestKind::GoTest(runner) => runner.detect_workspaces(args), AvailableTestKind::Vitest(runner) => runner.detect_workspaces(args), @@ -51,6 +56,7 @@ impl FromStr for AvailableTestKind { fn from_str(s: &str) -> Result { match s { "cargo-test" => Ok(AvailableTestKind::CargoTest(CargoTestRunner)), + "cargo-nextest" => Ok(AvailableTestKind::CargoNextest(CargoNextestRunner)), "jest" => Ok(AvailableTestKind::Jest(JestRunner)), "go-test" => Ok(AvailableTestKind::GoTest(GoTestRunner)), "vitest" => Ok(AvailableTestKind::Vitest(VitestRunner)), diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs new file mode 100644 index 0000000..7689d68 --- /dev/null +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -0,0 +1,197 @@ +use crate::runner::util::send_stdout; +use std::path::PathBuf; +use std::process::Output; +use std::str::FromStr; +use testing_language_server::error::LSError; +use testing_language_server::spec::DetectWorkspaceResult; +use testing_language_server::spec::RunFileTestResult; + +use testing_language_server::spec::DiscoverResult; +use testing_language_server::spec::DiscoverResultItem; + +use crate::model::Runner; + +use super::util::detect_workspaces_from_file_paths; +use super::util::discover_rust_tests; +use super::util::parse_cargo_diagnostics; + +fn parse_diagnostics( + contents: &str, + workspace_root: PathBuf, + file_paths: &[String], +) -> RunFileTestResult { + parse_cargo_diagnostics(contents, workspace_root, file_paths) +} + +fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { + detect_workspaces_from_file_paths(file_paths, &["Cargo.toml".to_string()]) +} + +#[derive(Eq, PartialEq, Hash, Debug)] +pub struct CargoNextestRunner; + +impl Runner for CargoNextestRunner { + fn disover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + let file_paths = args.file_paths; + let mut discover_results: DiscoverResult = vec![]; + + for file_path in file_paths { + let tests = discover_rust_tests(&file_path)?; + discover_results.push(DiscoverResultItem { + tests, + path: file_path, + }); + } + send_stdout(&discover_results)?; + Ok(()) + } + + fn run_file_test( + &self, + args: testing_language_server::spec::RunFileTestArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let tests = file_paths + .iter() + .map(|path| { + discover_rust_tests(path).map(|test_items| { + test_items + .into_iter() + .map(|item| item.id) + .collect::>() + }) + }) + .filter_map(Result::ok) + .flatten() + .collect::>(); + let workspace_root = args.workspace; + let test_result = std::process::Command::new("cargo") + .current_dir(&workspace_root) + .arg("nextest") + .arg("run") + .arg("--workspace") + .arg("--no-fail-fast") + .args(args.extra) + .arg("--") + .args(tests) + .output() + .unwrap(); + let Output { + stdout, + stderr, + status, + .. + } = test_result; + let unexpected_status_code = status.code().map(|code| code != 100); + if stdout.is_empty() && !stderr.is_empty() && unexpected_status_code.unwrap_or(false) { + return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); + } + let test_result = String::from_utf8(stderr)?; + let diagnostics: RunFileTestResult = parse_diagnostics( + &test_result, + PathBuf::from_str(&workspace_root).unwrap(), + &file_paths, + ); + send_stdout(&diagnostics)?; + Ok(()) + } + + fn detect_workspaces( + &self, + args: testing_language_server::spec::DetectWorkspaceArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let detect_result = detect_workspaces(&file_paths); + send_stdout(&detect_result)?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; + use testing_language_server::spec::RunFileTestResultItem; + + use crate::runner::util::MAX_CHAR_LENGTH; + + use super::*; + + #[test] + fn parse_test_results() { + let fixture = r#" +running 1 test +test rocks::dependency::tests::parse_dependency ... FAILED +failures: + Finished test [unoptimized + debuginfo] target(s) in 0.12s + Starting 1 test across 2 binaries (17 skipped) + FAIL [ 0.004s] rocks-lib rocks::dependency::tests::parse_dependency +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 17 filtered out; finis +hed in 0.00s +--- STDERR: rocks-lib rocks::dependency::tests::parse_dependency --- +thread 'rocks::dependency::tests::parse_dependency' panicked at rocks-lib/src/rocks/dependency.rs:86:64: +called `Result::unwrap()` on an `Err` value: unexpected end of input while parsing min or version number +Location: + rocks-lib/src/rocks/dependency.rs:62:22 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + + "#; + let file_paths = + vec!["/home/example/projects/rocks-lib/src/rocks/dependency.rs".to_string()]; + let diagnostics: RunFileTestResult = parse_diagnostics( + fixture, + PathBuf::from_str("/home/example/projects").unwrap(), + &file_paths, + ); + let message = r#"called `Result::unwrap()` on an `Err` value: unexpected end of input while parsing min or version number +Location: + rocks-lib/src/rocks/dependency.rs:62:22 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +"#; + + assert_eq!( + diagnostics, + vec![RunFileTestResultItem { + path: file_paths.first().unwrap().to_owned(), + diagnostics: vec![Diagnostic { + range: Range { + start: Position { + line: 85, + character: 63 + }, + end: Position { + line: 85, + character: MAX_CHAR_LENGTH + } + }, + message: message.to_string(), + severity: Some(DiagnosticSeverity::ERROR), + ..Diagnostic::default() + }] + }] + ) + } + + #[test] + fn test_discover() { + let file_path = "../../demo/rust/src/lib.rs"; + discover_rust_tests(file_path).unwrap(); + } + + #[test] + fn test_detect_workspaces() { + let current_dir = std::env::current_dir().unwrap(); + let librs = current_dir.join("src/lib.rs"); + let mainrs = current_dir.join("src/main.rs"); + let absolute_path_of_demo = current_dir.join("../../demo/rust"); + let demo_librs = absolute_path_of_demo.join("src/lib.rs"); + let file_paths: Vec = [librs, mainrs, demo_librs] + .iter() + .map(|file_path| file_path.to_str().unwrap().to_string()) + .collect(); + + let workspaces = detect_workspaces(&file_paths); + assert_eq!(workspaces.len(), 2); + assert!(workspaces.contains_key(absolute_path_of_demo.to_str().unwrap())); + assert!(workspaces.contains_key(current_dir.to_str().unwrap())); + } +} diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 1327022..6d94abe 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -1,191 +1,28 @@ use crate::runner::util::send_stdout; -use lsp_types::DiagnosticSeverity; -use std::collections::HashMap; use std::path::PathBuf; use std::process::Output; use std::str::FromStr; use testing_language_server::error::LSError; use testing_language_server::spec::DetectWorkspaceResult; use testing_language_server::spec::RunFileTestResult; -use testing_language_server::spec::TestItem; -use tree_sitter::Point; -use tree_sitter::Query; -use tree_sitter::QueryCursor; -use lsp_types::{Diagnostic, Position, Range}; -use regex::Regex; use testing_language_server::spec::DiscoverResult; use testing_language_server::spec::DiscoverResultItem; -use testing_language_server::spec::RunFileTestResultItem; use crate::model::Runner; use super::util::detect_workspaces_from_file_paths; +use super::util::discover_rust_tests; +use super::util::parse_cargo_diagnostics; // If the character value is greater than the line length it defaults back to the line length. -const MAX_CHAR_LENGTH: u32 = 10000; fn parse_diagnostics( contents: &str, workspace_root: PathBuf, file_paths: &[String], ) -> RunFileTestResult { - let contents = contents.replace("\r\n", "\n"); - let lines = contents.lines(); - let mut result_map: HashMap> = HashMap::new(); - for (i, line) in lines.clone().enumerate() { - let re = Regex::new(r"thread '([^']+)' panicked at ([^:]+):(\d+):(\d+):").unwrap(); - if let Some(m) = re.captures(line) { - let mut message = String::new(); - let file = m.get(2).unwrap().as_str().to_string(); - if let Some(file_path) = file_paths - .iter() - .find(|path| path.contains(workspace_root.join(&file).to_str().unwrap())) - { - let lnum = m.get(3).unwrap().as_str().parse::().unwrap() - 1; - let col = m.get(4).unwrap().as_str().parse::().unwrap() - 1; - let mut next_i = i + 1; - while next_i < lines.clone().count() - && !lines.clone().nth(next_i).unwrap().is_empty() - { - message = format!("{}{}\n", message, lines.clone().nth(next_i).unwrap()); - next_i += 1; - } - let diagnostic = Diagnostic { - range: Range { - start: Position { - line: lnum, - character: col, - }, - end: Position { - line: lnum, - character: MAX_CHAR_LENGTH, - }, - }, - message, - severity: Some(DiagnosticSeverity::ERROR), - ..Diagnostic::default() - }; - result_map - .entry(file_path.to_string()) - .or_default() - .push(diagnostic); - } else { - continue; - } - } - } - - result_map - .into_iter() - .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) - .collect() -} - -fn discover(file_path: &str) -> Result, LSError> { - let mut parser = tree_sitter::Parser::new(); - let mut test_items: Vec = vec![]; - parser - .set_language(&tree_sitter_rust::language()) - .expect("Error loading Rust grammar"); - let source_code = std::fs::read_to_string(file_path)?; - let tree = parser.parse(&source_code, None).unwrap(); - // from https://github.com/rouge8/neotest-rust/blob/0418811e1e3499b2501593f2e131d02f5e6823d4/lua/neotest-rust/init.lua#L167 - // license: https://github.com/rouge8/neotest-rust/blob/0418811e1e3499b2501593f2e131d02f5e6823d4/LICENSE - let query_string = r#" - ( - (attribute_item - [ - (attribute - (identifier) @macro_name - ) - (attribute - [ - (identifier) @macro_name - (scoped_identifier - name: (identifier) @macro_name - ) - ] - ) - ] - ) - [ - (attribute_item - (attribute - (identifier) - ) - ) - (line_comment) - ]* - . - (function_item - name: (identifier) @test.name - ) @test.definition - (#any-of? @macro_name "test" "rstest" "case") - -) -(mod_item name: (identifier) @namespace.name)? @namespace.definition -"#; - let query = - Query::new(&tree_sitter_rust::language(), query_string).expect("Error creating query"); - - let mut cursor = QueryCursor::new(); - cursor.set_byte_range(tree.root_node().byte_range()); - let source = source_code.as_bytes(); - let matches = cursor.matches(&query, tree.root_node(), source); - for m in matches { - let mut namespace_name = ""; - let mut test_start_position = Point::default(); - let mut test_end_position = Point::default(); - for capture in m.captures { - let capture_name = query.capture_names()[capture.index as usize]; - let value = capture.node.utf8_text(source)?; - let start_position = capture.node.start_position(); - let end_position = capture.node.end_position(); - match capture_name { - "namespace.name" => { - namespace_name = value; - } - "test.definition" => { - test_start_position = start_position; - test_end_position = end_position; - } - "test.name" => { - let test_name = value; - let test_item = TestItem { - id: format!("{}:{}", namespace_name, test_name), - name: test_name.to_string(), - start_position: Range { - start: Position { - line: test_start_position.row as u32, - character: test_start_position.column as u32, - }, - end: Position { - line: test_start_position.row as u32, - character: MAX_CHAR_LENGTH, - }, - }, - end_position: Range { - start: Position { - line: test_end_position.row as u32, - character: 0, - }, - end: Position { - line: test_end_position.row as u32, - character: test_end_position.column as u32, - }, - }, - }; - test_items.push(test_item); - test_start_position = Point::default(); - test_end_position = Point::default(); - } - _ => {} - } - } - } - - Ok(test_items) + parse_cargo_diagnostics(contents, workspace_root, file_paths) } fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { @@ -201,7 +38,7 @@ impl Runner for CargoTestRunner { let mut discover_results: DiscoverResult = vec![]; for file_path in file_paths { - let tests = discover(&file_path)?; + let tests = discover_rust_tests(&file_path)?; discover_results.push(DiscoverResultItem { tests, path: file_path, @@ -219,7 +56,7 @@ impl Runner for CargoTestRunner { let tests = file_paths .iter() .map(|path| { - discover(path).map(|test_items| { + discover_rust_tests(path).map(|test_items| { test_items .into_iter() .map(|item| item.id) @@ -265,6 +102,11 @@ impl Runner for CargoTestRunner { #[cfg(test)] mod tests { + use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; + use testing_language_server::spec::RunFileTestResultItem; + + use crate::runner::util::MAX_CHAR_LENGTH; + use super::*; #[test] @@ -325,7 +167,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace #[test] fn test_discover() { let file_path = "../../demo/rust/src/lib.rs"; - discover(file_path).unwrap(); + discover_rust_tests(file_path).unwrap(); } #[test] diff --git a/crates/adapter/src/runner/mod.rs b/crates/adapter/src/runner/mod.rs index 4dfec76..d595b38 100644 --- a/crates/adapter/src/runner/mod.rs +++ b/crates/adapter/src/runner/mod.rs @@ -1,3 +1,4 @@ +pub mod cargo_nextest; pub mod cargo_test; pub mod go; pub mod jest; diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index 20e891e..95f9691 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -2,9 +2,12 @@ use std::collections::HashMap; use std::path::PathBuf; use std::str::FromStr; +use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; use regex::Regex; use serde::Serialize; -use testing_language_server::error::LSError; +use testing_language_server::spec::{RunFileTestResultItem, TestItem}; +use testing_language_server::{error::LSError, spec::RunFileTestResult}; +use tree_sitter::{Point, Query, QueryCursor}; // If the character value is greater than the line length it defaults back to the line length. pub const MAX_CHAR_LENGTH: u32 = 10000; @@ -71,3 +74,166 @@ pub fn clean_ansi(input: &str) -> String { let re = Regex::new(r"\x1B\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]").unwrap(); re.replace_all(input, "").to_string() } + +pub fn discover_rust_tests(file_path: &str) -> Result, LSError> { + let mut parser = tree_sitter::Parser::new(); + let mut test_items: Vec = vec![]; + parser + .set_language(&tree_sitter_rust::language()) + .expect("Error loading Rust grammar"); + let source_code = std::fs::read_to_string(file_path)?; + let tree = parser.parse(&source_code, None).unwrap(); + // from https://github.com/rouge8/neotest-rust/blob/0418811e1e3499b2501593f2e131d02f5e6823d4/lua/neotest-rust/init.lua#L167 + // license: https://github.com/rouge8/neotest-rust/blob/0418811e1e3499b2501593f2e131d02f5e6823d4/LICENSE + let query_string = r#" + ( + (attribute_item + [ + (attribute + (identifier) @macro_name + ) + (attribute + [ + (identifier) @macro_name + (scoped_identifier + name: (identifier) @macro_name + ) + ] + ) + ] + ) + [ + (attribute_item + (attribute + (identifier) + ) + ) + (line_comment) + ]* + . + (function_item + name: (identifier) @test.name + ) @test.definition + (#any-of? @macro_name "test" "rstest" "case") + +) +(mod_item name: (identifier) @namespace.name)? @namespace.definition +"#; + let query = + Query::new(&tree_sitter_rust::language(), query_string).expect("Error creating query"); + + let mut cursor = QueryCursor::new(); + cursor.set_byte_range(tree.root_node().byte_range()); + let source = source_code.as_bytes(); + let matches = cursor.matches(&query, tree.root_node(), source); + for m in matches { + let mut namespace_name = ""; + let mut test_start_position = Point::default(); + let mut test_end_position = Point::default(); + for capture in m.captures { + let capture_name = query.capture_names()[capture.index as usize]; + let value = capture.node.utf8_text(source)?; + let start_position = capture.node.start_position(); + let end_position = capture.node.end_position(); + match capture_name { + "namespace.name" => { + namespace_name = value; + } + "test.definition" => { + test_start_position = start_position; + test_end_position = end_position; + } + "test.name" => { + let test_name = value; + let test_item = TestItem { + id: format!("{}:{}", namespace_name, test_name), + name: test_name.to_string(), + start_position: Range { + start: Position { + line: test_start_position.row as u32, + character: test_start_position.column as u32, + }, + end: Position { + line: test_start_position.row as u32, + character: MAX_CHAR_LENGTH, + }, + }, + end_position: Range { + start: Position { + line: test_end_position.row as u32, + character: 0, + }, + end: Position { + line: test_end_position.row as u32, + character: test_end_position.column as u32, + }, + }, + }; + test_items.push(test_item); + test_start_position = Point::default(); + test_end_position = Point::default(); + } + _ => {} + } + } + } + + Ok(test_items) +} + +pub fn parse_cargo_diagnostics( + contents: &str, + workspace_root: PathBuf, + file_paths: &[String], +) -> RunFileTestResult { + let contents = contents.replace("\r\n", "\n"); + let lines = contents.lines(); + let mut result_map: HashMap> = HashMap::new(); + for (i, line) in lines.clone().enumerate() { + let re = Regex::new(r"thread '([^']+)' panicked at ([^:]+):(\d+):(\d+):").unwrap(); + if let Some(m) = re.captures(line) { + let mut message = String::new(); + let file = m.get(2).unwrap().as_str().to_string(); + if let Some(file_path) = file_paths + .iter() + .find(|path| path.contains(workspace_root.join(&file).to_str().unwrap())) + { + let lnum = m.get(3).unwrap().as_str().parse::().unwrap() - 1; + let col = m.get(4).unwrap().as_str().parse::().unwrap() - 1; + let mut next_i = i + 1; + while next_i < lines.clone().count() + && !lines.clone().nth(next_i).unwrap().is_empty() + { + message = format!("{}{}\n", message, lines.clone().nth(next_i).unwrap()); + next_i += 1; + } + let diagnostic = Diagnostic { + range: Range { + start: Position { + line: lnum, + character: col, + }, + end: Position { + line: lnum, + character: MAX_CHAR_LENGTH, + }, + }, + message, + severity: Some(DiagnosticSeverity::ERROR), + ..Diagnostic::default() + }; + result_map + .entry(file_path.to_string()) + .or_default() + .push(diagnostic); + } else { + continue; + } + } + } + + result_map + .into_iter() + .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) + .collect() +} diff --git a/demo/.vim/coc-settings.json b/demo/.vim/coc-settings.json index e71c005..2b54395 100644 --- a/demo/.vim/coc-settings.json +++ b/demo/.vim/coc-settings.json @@ -6,10 +6,18 @@ "filetypes": ["rust", "javascript", "go", "typescript"], "initializationOptions": { "adapterCommand": { - "rust": [ + // "cargo-test": [ + // { + // "path": "testing-ls-adapter", + // "extra_args": ["--test-kind=cargo-test"], + // "include_patterns": ["/**/src/**/*.rs"], + // "exclude_patterns": ["/**/target/**"] + // } + // ], + "cargo-nextest": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=cargo-test"], + "extra_args": ["--test-kind=cargo-nextest"], "include_patterns": ["/**/src/**/*.rs"], "exclude_patterns": ["/**/target/**"] } From 6cb4fcbd927df3b401aa559f4ebc323c7983ae26 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 20 Jul 2024 23:39:24 +0900 Subject: [PATCH 021/139] feat(adapter): implement adapter for deno --- Cargo.lock | 4 +- crates/adapter/src/model.rs | 6 + crates/adapter/src/runner/deno.rs | 398 ++++++++++++++++++++++++++++++ crates/adapter/src/runner/mod.rs | 1 + crates/adapter/src/runner/util.rs | 26 +- demo/.vim/coc-settings.json | 11 +- demo/deno/deno.json | 5 + demo/deno/deno.lock | 21 ++ demo/deno/main.ts | 8 + demo/deno/main_test.ts | 18 ++ demo/deno/output.txt | 36 +++ 11 files changed, 530 insertions(+), 4 deletions(-) create mode 100644 crates/adapter/src/runner/deno.rs create mode 100644 demo/deno/deno.json create mode 100644 demo/deno/deno.lock create mode 100644 demo/deno/main.ts create mode 100644 demo/deno/main_test.ts create mode 100644 demo/deno/output.txt diff --git a/Cargo.lock b/Cargo.lock index 0daac9b..acc76be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,9 +89,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.96" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "066fce287b1d4eafef758e89e09d724a24808a9196fe9756b8ca90e86d0719a2" [[package]] name = "cfg-if" diff --git a/crates/adapter/src/model.rs b/crates/adapter/src/model.rs index 1169838..9a436cc 100644 --- a/crates/adapter/src/model.rs +++ b/crates/adapter/src/model.rs @@ -1,5 +1,6 @@ use crate::runner::cargo_nextest::CargoNextestRunner; use crate::runner::cargo_test::CargoTestRunner; +use crate::runner::deno::DenoRunner; use crate::runner::go::GoTestRunner; use crate::runner::vitest::VitestRunner; use std::str::FromStr; @@ -16,6 +17,7 @@ pub enum AvailableTestKind { CargoNextest(CargoNextestRunner), Jest(JestRunner), Vitest(VitestRunner), + Deno(DenoRunner), GoTest(GoTestRunner), } impl Runner for AvailableTestKind { @@ -24,6 +26,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::CargoTest(runner) => runner.disover(args), AvailableTestKind::CargoNextest(runner) => runner.disover(args), AvailableTestKind::Jest(runner) => runner.disover(args), + AvailableTestKind::Deno(runner) => runner.disover(args), AvailableTestKind::GoTest(runner) => runner.disover(args), AvailableTestKind::Vitest(runner) => runner.disover(args), } @@ -34,6 +37,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::CargoTest(runner) => runner.run_file_test(args), AvailableTestKind::CargoNextest(runner) => runner.run_file_test(args), AvailableTestKind::Jest(runner) => runner.run_file_test(args), + AvailableTestKind::Deno(runner) => runner.run_file_test(args), AvailableTestKind::GoTest(runner) => runner.run_file_test(args), AvailableTestKind::Vitest(runner) => runner.run_file_test(args), } @@ -44,6 +48,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::CargoTest(runner) => runner.detect_workspaces(args), AvailableTestKind::CargoNextest(runner) => runner.detect_workspaces(args), AvailableTestKind::Jest(runner) => runner.detect_workspaces(args), + AvailableTestKind::Deno(runner) => runner.detect_workspaces(args), AvailableTestKind::GoTest(runner) => runner.detect_workspaces(args), AvailableTestKind::Vitest(runner) => runner.detect_workspaces(args), } @@ -60,6 +65,7 @@ impl FromStr for AvailableTestKind { "jest" => Ok(AvailableTestKind::Jest(JestRunner)), "go-test" => Ok(AvailableTestKind::GoTest(GoTestRunner)), "vitest" => Ok(AvailableTestKind::Vitest(VitestRunner)), + "deno" => Ok(AvailableTestKind::Deno(DenoRunner)), _ => Err(anyhow::anyhow!("Unknown test kind: {}", s)), } } diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs new file mode 100644 index 0000000..d606543 --- /dev/null +++ b/crates/adapter/src/runner/deno.rs @@ -0,0 +1,398 @@ +use crate::runner::util::resolve_path; +use crate::runner::util::send_stdout; +use lsp_types::Diagnostic; +use lsp_types::DiagnosticSeverity; +use lsp_types::Position; +use lsp_types::Range; +use regex::Regex; +use std::collections::HashMap; +use std::path::PathBuf; +use std::process::Output; +use std::str::FromStr; +use testing_language_server::error::LSError; + +use testing_language_server::spec::DetectWorkspaceResult; +use testing_language_server::spec::DiscoverResult; +use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::RunFileTestResult; +use testing_language_server::spec::RunFileTestResultItem; +use testing_language_server::spec::TestItem; +use tree_sitter::Point; +use tree_sitter::Query; +use tree_sitter::QueryCursor; + +use crate::model::Runner; + +use super::util::clean_ansi; +use super::util::detect_workspaces_from_file_paths; +use super::util::MAX_CHAR_LENGTH; + +fn get_position_from_output(line: &str) -> Option<(String, u32, u32)> { + let re = Regex::new(r"=> (?P.*):(?P\d+):(?P\d+)").unwrap(); + + if let Some(captures) = re.captures(line) { + let file = captures.name("file").unwrap().as_str().to_string(); + let line = captures.name("line").unwrap().as_str().parse().unwrap(); + let column = captures.name("column").unwrap().as_str().parse().unwrap(); + + Some((file, line, column)) + } else { + None + } +} + +fn parse_diagnostics( + contents: &str, + workspace_root: PathBuf, + file_paths: &[String], +) -> Result { + let contents = clean_ansi(&contents.replace("\r\n", "\n")); + let lines = contents.lines(); + let mut result_map: HashMap> = HashMap::new(); + let mut file_name: Option = None; + let mut lnum: Option = None; + let mut message = String::new(); + let mut error_exists = false; + for line in lines { + if line.contains("ERRORS") { + error_exists = true; + } else if !error_exists { + continue; + } + if let Some(position) = get_position_from_output(line) { + if file_name.is_some() { + let diagnostic = Diagnostic { + range: Range { + start: Position { + line: lnum.unwrap(), + character: 1, + }, + end: Position { + line: lnum.unwrap(), + character: MAX_CHAR_LENGTH, + }, + }, + message: message.clone(), + severity: Some(DiagnosticSeverity::ERROR), + ..Diagnostic::default() + }; + let file_path = resolve_path(&workspace_root, file_name.as_ref().unwrap()) + .to_str() + .unwrap() + .to_string(); + if file_paths.contains(&file_path) { + result_map.entry(file_path).or_default().push(diagnostic); + } + } + file_name = Some(position.0); + lnum = Some(position.1); + } else { + message += line; + } + } + Ok(result_map + .into_iter() + .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) + .collect()) +} + +fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { + detect_workspaces_from_file_paths(&file_paths, &["deno.json".to_string()]) +} + +fn discover(file_path: &str) -> Result, LSError> { + let mut parser = tree_sitter::Parser::new(); + let mut test_items: Vec = vec![]; + parser + .set_language(&tree_sitter_javascript::language()) + .expect("Error loading JavaScript grammar"); + let source_code = std::fs::read_to_string(file_path)?; + let tree = parser.parse(&source_code, None).unwrap(); + // from https://github.com/MarkEmmons/neotest-deno/blob/7136b9342aeecb675c7c16a0bde327d7fcb00a1c/lua/neotest-deno/init.lua#L93 + // license: https://github.com/MarkEmmons/neotest-deno/blob/main/LICENSE + let query_string = r#" +;; Deno.test +(call_expression + function: (member_expression) @func_name (#match? @func_name "^Deno.test$") + arguments: [ + (arguments ((string) @test.name . (arrow_function))) + (arguments . (function_expression name: (identifier) @test.name)) + (arguments . (object(pair + key: (property_identifier) @key (#match? @key "^name$") + value: (string) @test.name + ))) + (arguments ((string) @test.name . (object) . (arrow_function))) + (arguments (object) . (function_expression name: (identifier) @test.name)) + ] +) @test.definition + +;; BDD describe - nested +(call_expression + function: (identifier) @func_name (#match? @func_name "^describe$") + arguments: [ + (arguments ((string) @namespace.name . (arrow_function))) + (arguments ((string) @namespace.name . (function_expression))) + ] +) @namespace.definition + +;; BDD describe - flat +(variable_declarator + name: (identifier) @namespace.id + value: (call_expression + function: (identifier) @func_name (#match? @func_name "^describe") + arguments: [ + (arguments ((string) @namespace.name)) + (arguments (object (pair + key: (property_identifier) @key (#match? @key "^name$") + value: (string) @namespace.name + ))) + ] + ) +) @namespace.definition + +;; BDD it +(call_expression + function: (identifier) @func_name (#match? @func_name "^it$") + arguments: [ + (arguments ((string) @test.name . (arrow_function))) + (arguments ((string) @test.name . (function_expression))) + ] +) @test.definition + "#; + let query = Query::new(&tree_sitter_javascript::language(), query_string) + .expect("Error creating query"); + let mut cursor = QueryCursor::new(); + cursor.set_byte_range(tree.root_node().byte_range()); + let source = source_code.as_bytes(); + let matches = cursor.matches(&query, tree.root_node(), source); + for m in matches { + eprintln!("DEBUGPRINT[3]: deno.rs:170: m={:#?}", m); + let mut namespace_name = ""; + let mut test_start_position = Point::default(); + let mut test_end_position = Point::default(); + for capture in m.captures { + let capture_name = query.capture_names()[capture.index as usize]; + let value = capture.node.utf8_text(source)?; + let start_position = capture.node.start_position(); + let end_position = capture.node.end_position(); + match capture_name { + "namespace.name" => { + namespace_name = value; + } + "test.definition" => { + test_start_position = start_position; + test_end_position = end_position; + } + "test.name" => { + let test_name = value; + let test_item = TestItem { + id: format!("{}:{}", namespace_name, test_name), + name: test_name.to_string(), + start_position: Range { + start: Position { + line: test_start_position.row as u32, + character: test_start_position.column as u32, + }, + end: Position { + line: test_start_position.row as u32, + character: MAX_CHAR_LENGTH, + }, + }, + end_position: Range { + start: Position { + line: test_end_position.row as u32, + character: 0, + }, + end: Position { + line: test_end_position.row as u32, + character: test_end_position.column as u32, + }, + }, + }; + test_items.push(test_item); + test_start_position = Point::default(); + test_end_position = Point::default(); + } + _ => {} + } + } + } + + Ok(test_items) +} + +#[derive(Eq, PartialEq, Debug)] +pub struct DenoRunner; + +impl Runner for DenoRunner { + fn disover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + let file_paths = args.file_paths; + let mut discover_results: DiscoverResult = vec![]; + for file_path in file_paths { + discover_results.push(DiscoverResultItem { + tests: discover(&file_path)?, + path: file_path, + }) + } + send_stdout(&discover_results)?; + Ok(()) + } + + fn run_file_test( + &self, + args: testing_language_server::spec::RunFileTestArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let workspace = args.workspace; + let output = std::process::Command::new("deno") + .current_dir(&workspace) + .args(["test", "--no-prompt"]) + .args(&file_paths) + .output() + .unwrap(); + let Output { stdout, stderr, .. } = output; + if stdout.is_empty() { + return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); + } + let test_result = String::from_utf8(stdout)?; + let diagnostics: RunFileTestResult = parse_diagnostics( + &test_result, + PathBuf::from_str(&workspace).unwrap(), + &file_paths, + )?; + send_stdout(&diagnostics)?; + Ok(()) + } + + fn detect_workspaces( + &self, + args: testing_language_server::spec::DetectWorkspaceArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let detect_result = detect_workspaces(file_paths); + send_stdout(&detect_result)?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use std::env::current_dir; + + use super::*; + + #[test] + fn test_parse_diagnostics() { + let test_result = std::env::current_dir() + .unwrap() + .join("../../demo/deno/output.txt"); + let test_result = std::fs::read_to_string(test_result).unwrap(); + let workspace = PathBuf::from_str("/home/demo/test/dneo/").unwrap(); + let target_file_path = "/home/demo/test/dneo/main_test.ts"; + let diagnostics = + parse_diagnostics(&test_result, workspace, &[target_file_path.to_string()]).unwrap(); + assert_eq!(diagnostics.len(), 1); + } + + #[test] + fn test_detect_workspace() { + let current_dir = std::env::current_dir().unwrap(); + let absolute_path_of_demo = current_dir.join("../../demo/deno"); + let test_file = absolute_path_of_demo.join("main.test.ts"); + let file_paths: Vec = [test_file] + .iter() + .map(|file_path| file_path.to_str().unwrap().to_string()) + .collect(); + let detect_result = detect_workspaces(file_paths); + assert_eq!(detect_result.len(), 1); + detect_result.iter().for_each(|(workspace, _)| { + assert_eq!(workspace, absolute_path_of_demo.to_str().unwrap()); + }); + } + + #[test] + fn test_discover() { + let file_path = current_dir().unwrap().join("../../demo/deno/main_test.ts"); + let file_path = file_path.to_str().unwrap(); + let test_items = discover(file_path).unwrap(); + assert_eq!(test_items.len(), 3); + assert_eq!( + test_items, + vec![ + TestItem { + id: String::from(":addTest"), + name: String::from("addTest"), + start_position: Range { + start: Position { + line: 7, + character: 0 + }, + end: Position { + line: 7, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 9, + character: 0 + }, + end: Position { + line: 9, + character: 2 + } + } + }, + TestItem { + id: String::from(":fail1"), + name: String::from("fail1"), + start_position: Range { + start: Position { + line: 11, + character: 0 + }, + end: Position { + line: 11, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 13, + character: 0 + }, + end: Position { + line: 13, + character: 2 + } + } + }, + TestItem { + id: String::from(":fail1"), + name: String::from("fail1"), + start_position: Range { + start: Position { + line: 15, + character: 0 + }, + end: Position { + line: 15, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 17, + character: 0 + }, + end: Position { + line: 17, + character: 2 + } + } + } + ] + ) + } +} diff --git a/crates/adapter/src/runner/mod.rs b/crates/adapter/src/runner/mod.rs index d595b38..ba750e2 100644 --- a/crates/adapter/src/runner/mod.rs +++ b/crates/adapter/src/runner/mod.rs @@ -1,5 +1,6 @@ pub mod cargo_nextest; pub mod cargo_test; +pub mod deno; pub mod go; pub mod jest; pub mod util; diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index 95f9691..fca47a6 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::str::FromStr; use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; @@ -237,3 +237,27 @@ pub fn parse_cargo_diagnostics( .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) .collect() } + +/// remove this function because duplicate implementation +pub fn resolve_path(base_dir: &Path, relative_path: &str) -> PathBuf { + let absolute = if Path::new(relative_path).is_absolute() { + PathBuf::from(relative_path) + } else { + base_dir.join(relative_path) + }; + + let mut components = Vec::new(); + for component in absolute.components() { + match component { + std::path::Component::ParentDir => { + components.pop(); + } + std::path::Component::Normal(_) | std::path::Component::RootDir => { + components.push(component); + } + _ => {} + } + } + + PathBuf::from_iter(components) +} diff --git a/demo/.vim/coc-settings.json b/demo/.vim/coc-settings.json index 2b54395..c67a4dd 100644 --- a/demo/.vim/coc-settings.json +++ b/demo/.vim/coc-settings.json @@ -41,6 +41,14 @@ "exclude_patterns": ["/vitest/**/node_modules/**/*"] } ], + "deno": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=deno"], + "include_patterns": ["/deno/*.ts"], + "exclude_patterns": [] + } + ], "go": [ { "path": "testing-ls-adapter", @@ -52,5 +60,6 @@ } } } - } + }, + "deno.enable": true } diff --git a/demo/deno/deno.json b/demo/deno/deno.json new file mode 100644 index 0000000..3c5130f --- /dev/null +++ b/demo/deno/deno.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "dev": "deno run --watch main.ts" + } +} diff --git a/demo/deno/deno.lock b/demo/deno/deno.lock new file mode 100644 index 0000000..bc122ba --- /dev/null +++ b/demo/deno/deno.lock @@ -0,0 +1,21 @@ +{ + "version": "3", + "packages": { + "specifiers": { + "jsr:@std/assert": "jsr:@std/assert@1.0.0", + "jsr:@std/internal@^1.0.1": "jsr:@std/internal@1.0.1" + }, + "jsr": { + "@std/assert@1.0.0": { + "integrity": "0e4f6d873f7f35e2a1e6194ceee39686c996b9e5d134948e644d35d4c4df2008", + "dependencies": [ + "jsr:@std/internal@^1.0.1" + ] + }, + "@std/internal@1.0.1": { + "integrity": "6f8c7544d06a11dd256c8d6ba54b11ed870aac6c5aeafff499892662c57673e6" + } + } + }, + "remote": {} +} diff --git a/demo/deno/main.ts b/demo/deno/main.ts new file mode 100644 index 0000000..be043e9 --- /dev/null +++ b/demo/deno/main.ts @@ -0,0 +1,8 @@ +export function add(a: number, b: number): number { + return a + b; +} + +// Learn more at https://deno.land/manual/examples/module_metadata#concepts +if (import.meta.main) { + console.log("Add 2 + 3 =", add(2, 3)); +} diff --git a/demo/deno/main_test.ts b/demo/deno/main_test.ts new file mode 100644 index 0000000..4604e1f --- /dev/null +++ b/demo/deno/main_test.ts @@ -0,0 +1,18 @@ +import { assert, assertEquals } from "jsr:@std/assert"; +import { add } from "./main.ts"; + +const throwFn = () => { + throw new Error("error"); +}; + +Deno.test(function addTest() { + assertEquals(add(2, 3), 5); +}); + +Deno.test(function fail1() { + assertEquals(add(2, 5), 5); +}); + +Deno.test(function fail1() { + assert(throwFn()); +}); diff --git a/demo/deno/output.txt b/demo/deno/output.txt new file mode 100644 index 0000000..043c563 --- /dev/null +++ b/demo/deno/output.txt @@ -0,0 +1,36 @@ +running 3 tests from ./main_test.ts +addTest ... ok (0ms) +fail1 ... FAILED (1ms) +fail1 ... FAILED (0ms) + + ERRORS  + +fail1 => ./main_test.ts:12:6 +error: AssertionError: Values are not equal. + + + [Diff] Actual / Expected + + +- 7 ++ 5 + + throw new AssertionError(message); + ^ + at assertEquals (https://jsr.io/@std/assert/1.0.0/equals.ts:47:9) + at fail1 (file:///home/demo/test/dneo/main_test.ts:13:3) + +fail1 => ./main_test.ts:16:6 +error: Error: error + throw new Error("error"); + ^ + at throwFn (file:///home/demo/test/dneo/main_test.ts:5:9) + at fail1 (file:///home/demo/test/dneo/main_test.ts:17:10) + + FAILURES  + +fail1 => ./main_test.ts:12:6 +fail1 => ./main_test.ts:16:6 + +FAILED | 1 passed | 2 failed (3ms) + From d8bd53d4caddf177025550f1e5ee2c6e844547d5 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 22 Jul 2024 23:21:13 +0900 Subject: [PATCH 022/139] refactor(adapter): unify repetitive code patterns --- crates/adapter/src/runner/cargo_test.rs | 2 - crates/adapter/src/runner/deno.rs | 74 +---------------------- crates/adapter/src/runner/go.rs | 78 ++---------------------- crates/adapter/src/runner/jest.rs | 79 ++----------------------- crates/adapter/src/runner/util.rs | 29 +++++---- crates/adapter/src/runner/vitest.rs | 78 +++--------------------- 6 files changed, 36 insertions(+), 304 deletions(-) diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 6d94abe..bf98fe3 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -15,8 +15,6 @@ use super::util::detect_workspaces_from_file_paths; use super::util::discover_rust_tests; use super::util::parse_cargo_diagnostics; -// If the character value is greater than the line length it defaults back to the line length. - fn parse_diagnostics( contents: &str, workspace_root: PathBuf, diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index d606543..eb63ce6 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -17,14 +17,12 @@ use testing_language_server::spec::DiscoverResultItem; use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::RunFileTestResultItem; use testing_language_server::spec::TestItem; -use tree_sitter::Point; -use tree_sitter::Query; -use tree_sitter::QueryCursor; use crate::model::Runner; use super::util::clean_ansi; use super::util::detect_workspaces_from_file_paths; +use super::util::discover_with_treesitter; use super::util::MAX_CHAR_LENGTH; fn get_position_from_output(line: &str) -> Option<(String, u32, u32)> { @@ -101,16 +99,9 @@ fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { } fn discover(file_path: &str) -> Result, LSError> { - let mut parser = tree_sitter::Parser::new(); - let mut test_items: Vec = vec![]; - parser - .set_language(&tree_sitter_javascript::language()) - .expect("Error loading JavaScript grammar"); - let source_code = std::fs::read_to_string(file_path)?; - let tree = parser.parse(&source_code, None).unwrap(); // from https://github.com/MarkEmmons/neotest-deno/blob/7136b9342aeecb675c7c16a0bde327d7fcb00a1c/lua/neotest-deno/init.lua#L93 // license: https://github.com/MarkEmmons/neotest-deno/blob/main/LICENSE - let query_string = r#" + let query = r#" ;; Deno.test (call_expression function: (member_expression) @func_name (#match? @func_name "^Deno.test$") @@ -159,66 +150,7 @@ fn discover(file_path: &str) -> Result, LSError> { ] ) @test.definition "#; - let query = Query::new(&tree_sitter_javascript::language(), query_string) - .expect("Error creating query"); - let mut cursor = QueryCursor::new(); - cursor.set_byte_range(tree.root_node().byte_range()); - let source = source_code.as_bytes(); - let matches = cursor.matches(&query, tree.root_node(), source); - for m in matches { - eprintln!("DEBUGPRINT[3]: deno.rs:170: m={:#?}", m); - let mut namespace_name = ""; - let mut test_start_position = Point::default(); - let mut test_end_position = Point::default(); - for capture in m.captures { - let capture_name = query.capture_names()[capture.index as usize]; - let value = capture.node.utf8_text(source)?; - let start_position = capture.node.start_position(); - let end_position = capture.node.end_position(); - match capture_name { - "namespace.name" => { - namespace_name = value; - } - "test.definition" => { - test_start_position = start_position; - test_end_position = end_position; - } - "test.name" => { - let test_name = value; - let test_item = TestItem { - id: format!("{}:{}", namespace_name, test_name), - name: test_name.to_string(), - start_position: Range { - start: Position { - line: test_start_position.row as u32, - character: test_start_position.column as u32, - }, - end: Position { - line: test_start_position.row as u32, - character: MAX_CHAR_LENGTH, - }, - }, - end_position: Range { - start: Position { - line: test_end_position.row as u32, - character: 0, - }, - end: Position { - line: test_end_position.row as u32, - character: test_end_position.column as u32, - }, - }, - }; - test_items.push(test_item); - test_start_position = Point::default(); - test_end_position = Point::default(); - } - _ => {} - } - } - } - - Ok(test_items) + discover_with_treesitter(file_path, &tree_sitter_javascript::language(), query) } #[derive(Eq, PartialEq, Debug)] diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 2034709..3d9e822 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -17,14 +17,10 @@ use testing_language_server::spec::DiscoverResultItem; use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::RunFileTestResultItem; use testing_language_server::spec::TestItem; -use tree_sitter::Point; -use tree_sitter::Query; -use tree_sitter::QueryCursor; use super::util::detect_workspaces_from_file_paths; - -// If the character value is greater than the line length it defaults back to the line length. -const MAX_CHAR_LENGTH: u32 = 10000; +use super::util::discover_with_treesitter; +use super::util::MAX_CHAR_LENGTH; #[derive(Deserialize, Eq, PartialEq)] #[serde(rename_all = "camelCase")] @@ -140,16 +136,9 @@ fn parse_diagnostics( } fn discover(file_path: &str) -> Result, LSError> { - let mut parser = tree_sitter::Parser::new(); - let mut test_items: Vec = vec![]; - parser - .set_language(&tree_sitter_go::language()) - .expect("Error loading Rust grammar"); - let source_code = std::fs::read_to_string(file_path)?; - let tree = parser.parse(&source_code, None).unwrap(); // from https://github.com/nvim-neotest/neotest-go/blob/92950ad7be2ca02a41abca5c6600ff6ffaf5b5d6/lua/neotest-go/init.lua#L54 // license: https://github.com/nvim-neotest/neotest-go/blob/92950ad7be2ca02a41abca5c6600ff6ffaf5b5d6/README.md - let query_string = r#" + let query = r#" ;;query ((function_declaration name: (identifier) @test.name) @@ -230,66 +219,7 @@ fn discover(file_path: &str) -> Result, LSError> { ((identifier) @test.key.name1 (#eq? @test.key.name @test.key.name1)))))))) "#; - let query = - Query::new(&tree_sitter_go::language(), query_string).expect("Error creating query"); - - let mut cursor = QueryCursor::new(); - cursor.set_byte_range(tree.root_node().byte_range()); - let source = source_code.as_bytes(); - let matches = cursor.matches(&query, tree.root_node(), source); - for m in matches { - let mut namespace_name = ""; - let mut test_start_position = Point::default(); - let mut test_end_position = Point::default(); - for capture in m.captures { - let capture_name = query.capture_names()[capture.index as usize]; - let value = capture.node.utf8_text(source)?; - let start_position = capture.node.start_position(); - let end_position = capture.node.end_position(); - match capture_name { - "namespace.name" => { - namespace_name = value; - } - "test.definition" => { - test_start_position = start_position; - test_end_position = end_position; - } - "test.name" => { - let test_name = value; - let test_item = TestItem { - id: format!("{}:{}", namespace_name, test_name), - name: test_name.to_string(), - start_position: Range { - start: Position { - line: test_start_position.row as u32, - character: test_start_position.column as u32, - }, - end: Position { - line: test_start_position.row as u32, - character: MAX_CHAR_LENGTH, - }, - }, - end_position: Range { - start: Position { - line: test_end_position.row as u32, - character: 0, - }, - end: Position { - line: test_end_position.row as u32, - character: test_end_position.column as u32, - }, - }, - }; - test_items.push(test_item); - test_start_position = Point::default(); - test_end_position = Point::default(); - } - _ => {} - } - } - } - - Ok(test_items) + discover_with_treesitter(file_path, &tree_sitter_go::language(), query) } #[derive(Eq, PartialEq, Hash, Debug)] diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 541212e..379fa1d 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -1,8 +1,6 @@ use crate::runner::util::send_stdout; use lsp_types::Diagnostic; use lsp_types::DiagnosticSeverity; -use lsp_types::Position; -use lsp_types::Range; use serde_json::Value; use std::collections::HashMap; use std::fs; @@ -15,17 +13,13 @@ use testing_language_server::spec::DiscoverResultItem; use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::RunFileTestResultItem; use testing_language_server::spec::TestItem; -use tree_sitter::Point; -use tree_sitter::Query; -use tree_sitter::QueryCursor; use crate::model::Runner; use super::util::clean_ansi; use super::util::detect_workspaces_from_file_paths; - -// If the character value is greater than the line length it defaults back to the line length. -const MAX_CHAR_LENGTH: u32 = 10000; +use super::util::discover_with_treesitter; +use super::util::MAX_CHAR_LENGTH; fn parse_diagnostics( test_result: &str, @@ -84,16 +78,9 @@ fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { } fn discover(file_path: &str) -> Result, LSError> { - let mut parser = tree_sitter::Parser::new(); - let mut test_items: Vec = vec![]; - parser - .set_language(&tree_sitter_javascript::language()) - .expect("Error loading JavaScript grammar"); - let source_code = std::fs::read_to_string(file_path)?; - let tree = parser.parse(&source_code, None).unwrap(); // from https://github.com/nvim-neotest/neotest-jest/blob/514fd4eae7da15fd409133086bb8e029b65ac43f/lua/neotest-jest/init.lua#L162 // license: https://github.com/nvim-neotest/neotest-jest/blob/514fd4eae7da15fd409133086bb8e029b65ac43f/LICENSE.md - let query_string = r#" + let query = r#" ; -- Namespaces -- ; Matches: `describe('context', () => {})` ((call_expression @@ -162,65 +149,7 @@ fn discover(file_path: &str) -> Result, LSError> { arguments: (arguments (string (string_fragment) @test.name) [(arrow_function) (function_expression)]) )) @test.definition "#; - let query = Query::new(&tree_sitter_javascript::language(), query_string) - .expect("Error creating query"); - let mut cursor = QueryCursor::new(); - cursor.set_byte_range(tree.root_node().byte_range()); - let source = source_code.as_bytes(); - let matches = cursor.matches(&query, tree.root_node(), source); - for m in matches { - let mut namespace_name = ""; - let mut test_start_position = Point::default(); - let mut test_end_position = Point::default(); - for capture in m.captures { - let capture_name = query.capture_names()[capture.index as usize]; - let value = capture.node.utf8_text(source)?; - let start_position = capture.node.start_position(); - let end_position = capture.node.end_position(); - match capture_name { - "namespace.name" => { - namespace_name = value; - } - "test.definition" => { - test_start_position = start_position; - test_end_position = end_position; - } - "test.name" => { - let test_name = value; - let test_item = TestItem { - id: format!("{}:{}", namespace_name, test_name), - name: test_name.to_string(), - start_position: Range { - start: Position { - line: test_start_position.row as u32, - character: test_start_position.column as u32, - }, - end: Position { - line: test_start_position.row as u32, - character: MAX_CHAR_LENGTH, - }, - }, - end_position: Range { - start: Position { - line: test_end_position.row as u32, - character: 0, - }, - end: Position { - line: test_end_position.row as u32, - character: test_end_position.column as u32, - }, - }, - }; - test_items.push(test_item); - test_start_position = Point::default(); - test_end_position = Point::default(); - } - _ => {} - } - } - } - - Ok(test_items) + discover_with_treesitter(file_path, &tree_sitter_javascript::language(), query) } #[derive(Eq, PartialEq, Debug)] diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index fca47a6..f266284 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -7,7 +7,7 @@ use regex::Regex; use serde::Serialize; use testing_language_server::spec::{RunFileTestResultItem, TestItem}; use testing_language_server::{error::LSError, spec::RunFileTestResult}; -use tree_sitter::{Point, Query, QueryCursor}; +use tree_sitter::{Language, Point, Query, QueryCursor}; // If the character value is greater than the line length it defaults back to the line length. pub const MAX_CHAR_LENGTH: u32 = 10000; @@ -76,16 +76,9 @@ pub fn clean_ansi(input: &str) -> String { } pub fn discover_rust_tests(file_path: &str) -> Result, LSError> { - let mut parser = tree_sitter::Parser::new(); - let mut test_items: Vec = vec![]; - parser - .set_language(&tree_sitter_rust::language()) - .expect("Error loading Rust grammar"); - let source_code = std::fs::read_to_string(file_path)?; - let tree = parser.parse(&source_code, None).unwrap(); // from https://github.com/rouge8/neotest-rust/blob/0418811e1e3499b2501593f2e131d02f5e6823d4/lua/neotest-rust/init.lua#L167 // license: https://github.com/rouge8/neotest-rust/blob/0418811e1e3499b2501593f2e131d02f5e6823d4/LICENSE - let query_string = r#" + let query = r#" ( (attribute_item [ @@ -119,8 +112,22 @@ pub fn discover_rust_tests(file_path: &str) -> Result, LSError> { ) (mod_item name: (identifier) @namespace.name)? @namespace.definition "#; - let query = - Query::new(&tree_sitter_rust::language(), query_string).expect("Error creating query"); + discover_with_treesitter(file_path, &tree_sitter_rust::language(), query) +} + +pub fn discover_with_treesitter( + file_path: &str, + language: &Language, + query: &str, +) -> Result, LSError> { + let mut parser = tree_sitter::Parser::new(); + let mut test_items: Vec = vec![]; + parser + .set_language(language) + .expect("Error loading Rust grammar"); + let source_code = std::fs::read_to_string(file_path)?; + let tree = parser.parse(&source_code, None).unwrap(); + let query = Query::new(language, query).expect("Error creating query"); let mut cursor = QueryCursor::new(); cursor.set_byte_range(tree.root_node().byte_range()); diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 34549f0..193b60b 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -3,7 +3,7 @@ use std::{ fs::{self, File}, }; -use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; +use lsp_types::{Diagnostic, DiagnosticSeverity}; use serde_json::Value; use tempfile::tempdir; use testing_language_server::{ @@ -12,25 +12,20 @@ use testing_language_server::{ DiscoverResult, DiscoverResultItem, RunFileTestResult, RunFileTestResultItem, TestItem, }, }; -use tree_sitter::{Point, Query, QueryCursor}; use crate::model::Runner; -use super::util::{clean_ansi, detect_workspaces_from_file_paths, send_stdout, MAX_CHAR_LENGTH}; +use super::util::{ + clean_ansi, detect_workspaces_from_file_paths, discover_with_treesitter, send_stdout, + MAX_CHAR_LENGTH, +}; #[derive(Eq, PartialEq, Hash, Debug)] pub struct VitestRunner; fn discover(file_path: &str) -> Result, LSError> { - let mut parser = tree_sitter::Parser::new(); - let mut test_items: Vec = vec![]; - parser - .set_language(&tree_sitter_javascript::language()) - .expect("Error loading Rust grammar"); - let source_code = std::fs::read_to_string(file_path)?; - let tree = parser.parse(&source_code, None).unwrap(); // from https://github.com/marilari88/neotest-vitest/blob/353364aa05b94b09409cbef21b79c97c5564e2ce/lua/neotest-vitest/init.lua#L101 - let query_string = r#" + let query = r#" ; -- Namespaces -- ; Matches: `describe('context')` ((call_expression @@ -77,66 +72,7 @@ fn discover(file_path: &str) -> Result, LSError> { arguments: (arguments (string (string_fragment) @test.name) (arrow_function)) )) @test.definition "#; - let query = Query::new(&tree_sitter_javascript::language(), query_string) - .expect("Error creating query"); - - let mut cursor = QueryCursor::new(); - cursor.set_byte_range(tree.root_node().byte_range()); - let source = source_code.as_bytes(); - let matches = cursor.matches(&query, tree.root_node(), source); - for m in matches { - let mut namespace_name = ""; - let mut test_start_position = Point::default(); - let mut test_end_position = Point::default(); - for capture in m.captures { - let capture_name = query.capture_names()[capture.index as usize]; - let value = capture.node.utf8_text(source)?; - let start_position = capture.node.start_position(); - let end_position = capture.node.end_position(); - match capture_name { - "namespace.name" => { - namespace_name = value; - } - "test.definition" => { - test_start_position = start_position; - test_end_position = end_position; - } - "test.name" => { - let test_name = value; - let test_item = TestItem { - id: format!("{}:{}", namespace_name, test_name), - name: test_name.to_string(), - start_position: Range { - start: Position { - line: test_start_position.row as u32, - character: test_start_position.column as u32, - }, - end: Position { - line: test_start_position.row as u32, - character: MAX_CHAR_LENGTH, - }, - }, - end_position: Range { - start: Position { - line: test_end_position.row as u32, - character: 0, - }, - end: Position { - line: test_end_position.row as u32, - character: test_end_position.column as u32, - }, - }, - }; - test_items.push(test_item); - test_start_position = Point::default(); - test_end_position = Point::default(); - } - _ => {} - } - } - } - - Ok(test_items) + discover_with_treesitter(file_path, &tree_sitter_javascript::language(), query) } fn parse_diagnostics( From c3d3ff2c67cc03fbe8d304d0f87dc8279825c4a2 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 22 Jul 2024 23:35:34 +0900 Subject: [PATCH 023/139] refactor: rename method --- src/server.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/server.rs b/src/server.rs index 7e9ea27..305a94c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -145,7 +145,7 @@ impl TestingLS { self.initialize(id)?; } "workspace/diagnostic" => { - self.check_workspace()?; + self.diagnose_workspace()?; } "textDocument/diagnostic" | "textDocument/didSave" => { let uri = params["textDocument"]["uri"] @@ -330,7 +330,7 @@ impl TestingLS { Ok(()) } - pub fn check_workspace(&mut self) -> Result<(), LSError> { + pub fn diagnose_workspace(&mut self) -> Result<(), LSError> { self.refresh_workspaces_cache()?; self.workspaces_cache.iter().for_each( @@ -339,7 +339,7 @@ impl TestingLS { workspaces, }| { workspaces.iter().for_each(|(workspace, paths)| { - let _ = self.check(adapter, workspace, paths); + let _ = self.diagnose(adapter, workspace, paths); }) }, ); @@ -380,7 +380,7 @@ impl TestingLS { if !paths.contains(&path.to_string()) { continue; } - let _ = self.check(adapter, workspace, &[path.to_string()]); + let _ = self.diagnose(adapter, workspace, &[path.to_string()]); } }, ); @@ -457,7 +457,7 @@ impl TestingLS { Ok(diagnostics) } - fn check( + fn diagnose( &self, adapter: &AdapterConfiguration, workspace: &str, @@ -623,7 +623,7 @@ mod tests { }, workspaces_cache: Vec::new(), }; - server.check_workspace().unwrap(); + server.diagnose_workspace().unwrap(); server .workspaces_cache .iter() From 22401774e10e7bfedbf7ad6522fd1d52e202de03 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 3 Aug 2024 23:43:12 +0900 Subject: [PATCH 024/139] refactor: remove some `.clone()` --- src/server.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/server.rs b/src/server.rs index 305a94c..1e41eba 100644 --- a/src/server.rs +++ b/src/server.rs @@ -78,10 +78,10 @@ impl TestingLS { } else { let default_project_dir = self .initialize_params - .clone() .workspace_folders + .as_ref() .ok_or(LSError::Any(anyhow::anyhow!("No workspace folders found")))?; - let default_workspace_uri = default_project_dir[0].uri.clone(); + let default_workspace_uri = &default_project_dir[0].uri; Ok(default_workspace_uri.to_file_path().unwrap()) } } @@ -271,9 +271,9 @@ impl TestingLS { let project_dir = self.project_dir()?; self.workspaces_cache = vec![]; // Nested and multiple loops, but each count is small - for adapter_commands in adapter_commands.values() { - for adapter in adapter_commands { - let &AdapterConfiguration { + for adapter_commands in adapter_commands.into_values() { + for adapter in adapter_commands.into_iter() { + let AdapterConfiguration { path, extra_args, envs, @@ -313,12 +313,12 @@ impl TestingLS { .into_iter() .flat_map(|kv| kv.1) .collect::>(); - HashMap::from([(workspace_dir.clone(), target_paths)]) + HashMap::from([(workspace_dir, target_paths)]) } else { workspace }; self.workspaces_cache - .push(WorkspaceAnalysis::new(adapter.clone(), workspace)) + .push(WorkspaceAnalysis::new(adapter, workspace)) } } tracing::info!("workspaces_cache={:#?}", self.workspaces_cache); @@ -413,8 +413,8 @@ impl TestingLS { .map_err(|err| LSError::Adapter(err.to_string()))?; let Output { stdout, stderr, .. } = output; if !stderr.is_empty() { - let message = "Cannot run test command: \n".to_string() - + &String::from_utf8(stderr.clone()).unwrap(); + let message = + "Cannot run test command: \n".to_string() + &String::from_utf8(stderr).unwrap(); let placeholder_diagnostic = Diagnostic { range: Range { start: Position { @@ -446,9 +446,9 @@ impl TestingLS { for target_file in paths { let diagnostics_for_file: Vec = res .clone() - .iter() + .into_iter() .filter(|RunFileTestResultItem { path, .. }| path == target_file) - .flat_map(|RunFileTestResultItem { diagnostics, .. }| diagnostics.clone()) + .flat_map(|RunFileTestResultItem { diagnostics, .. }| diagnostics) .collect(); let uri = Url::from_file_path(target_file.replace("file://", "")).unwrap(); diagnostics.push((uri.to_string(), diagnostics_for_file)); From 4e1b8024850163ccc8a3bea2328e2848a8957daa Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 3 Aug 2024 23:45:26 +0900 Subject: [PATCH 025/139] refactor(demo): remove yarn related files --- demo/vitest/.yarnrc.yml | 1 - demo/vitest/yarn.lock | 1575 --------------------------------------- 2 files changed, 1576 deletions(-) delete mode 100644 demo/vitest/.yarnrc.yml delete mode 100644 demo/vitest/yarn.lock diff --git a/demo/vitest/.yarnrc.yml b/demo/vitest/.yarnrc.yml deleted file mode 100644 index 3186f3f..0000000 --- a/demo/vitest/.yarnrc.yml +++ /dev/null @@ -1 +0,0 @@ -nodeLinker: node-modules diff --git a/demo/vitest/yarn.lock b/demo/vitest/yarn.lock deleted file mode 100644 index 90eb480..0000000 --- a/demo/vitest/yarn.lock +++ /dev/null @@ -1,1575 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@cspotcode/source-map-support@npm:^0.8.0": - version: 0.8.1 - resolution: "@cspotcode/source-map-support@npm:0.8.1" - dependencies: - "@jridgewell/trace-mapping": "npm:0.3.9" - checksum: 10c0/05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.14.54": - version: 0.14.54 - resolution: "@esbuild/linux-loong64@npm:0.14.54" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.0.3": - version: 3.1.0 - resolution: "@jridgewell/resolve-uri@npm:3.1.0" - checksum: 10c0/78055e2526108331126366572045355051a930f017d1904a4f753d3f4acee8d92a14854948095626f6163cffc24ea4e3efa30637417bb866b84743dec7ef6fd9 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.14 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" - checksum: 10c0/3fbaff1387c1338b097eeb6ff92890d7838f7de0dde259e4983763b44540bfd5ca6a1f7644dc8ad003a57f7e80670d5b96a8402f1386ba9aee074743ae9bad51 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:0.3.9": - version: 0.3.9 - resolution: "@jridgewell/trace-mapping@npm:0.3.9" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.0.3" - "@jridgewell/sourcemap-codec": "npm:^1.4.10" - checksum: 10c0/fa425b606d7c7ee5bfa6a31a7b050dd5814b4082f318e0e4190f991902181b4330f43f4805db1dd4f2433fd0ed9cc7a7b9c2683f1deeab1df1b0a98b1e24055b - languageName: node - linkType: hard - -"@npmcli/agent@npm:^2.0.0": - version: 2.2.2 - resolution: "@npmcli/agent@npm:2.2.2" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae - languageName: node - linkType: hard - -"@npmcli/fs@npm:^3.1.0": - version: 3.1.1 - resolution: "@npmcli/fs@npm:3.1.1" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: 10c0/c176a2c1e1b16be120c328300ea910df15fb9a5277010116d26818272341a11483c5a80059389d04edacf6fd2d03d4687ad3660870fdd1cc0b7109e160adb220 - languageName: node - linkType: hard - -"@tsconfig/node12@npm:^1.0.7": - version: 1.0.11 - resolution: "@tsconfig/node12@npm:1.0.11" - checksum: 10c0/dddca2b553e2bee1308a056705103fc8304e42bb2d2cbd797b84403a223b25c78f2c683ec3e24a095e82cd435387c877239bffcb15a590ba817cd3f6b9a99fd9 - languageName: node - linkType: hard - -"@tsconfig/node14@npm:^1.0.0": - version: 1.0.3 - resolution: "@tsconfig/node14@npm:1.0.3" - checksum: 10c0/67c1316d065fdaa32525bc9449ff82c197c4c19092b9663b23213c8cbbf8d88b6ed6a17898e0cbc2711950fbfaf40388938c1c748a2ee89f7234fc9e7fe2bf44 - languageName: node - linkType: hard - -"@tsconfig/node16@npm:^1.0.2": - version: 1.0.3 - resolution: "@tsconfig/node16@npm:1.0.3" - checksum: 10c0/451a0d4b2bc35c2cdb30a49b6c699d797b8bbac99b883237659698678076d4193050d90e2ee36016ccbca57075cdb073cadab38cedc45119bac68ab331958cbc - languageName: node - linkType: hard - -"@types/chai-subset@npm:^1.3.3": - version: 1.3.3 - resolution: "@types/chai-subset@npm:1.3.3" - dependencies: - "@types/chai": "npm:*" - checksum: 10c0/2dfb3210ce8d872288bb44329a44d4d1b7be360c72e8eb570a535c0e97246a4bd0209df304427d0e179c9e1c659d5dba07c25bdae13ef983edf41db81278fda5 - languageName: node - linkType: hard - -"@types/chai@npm:*, @types/chai@npm:^4.3.3": - version: 4.3.3 - resolution: "@types/chai@npm:4.3.3" - checksum: 10c0/4129cb6119d65166cc082cecca97ddcf7d24785a4a55de2e06f3f1dc4c9543340168833ebdbc16685838cdea388854badc1453393dc90597725decfc20e05aff - languageName: node - linkType: hard - -"@types/node@npm:*, @types/node@npm:^18.0.3": - version: 18.7.8 - resolution: "@types/node@npm:18.7.8" - checksum: 10c0/ce4d37ff77ef2e1a180a2a4fc26e4df4f5b7af39f555500aa2fbb96c364e67b36f65ef100be183ef1e4f382767265ae22f1c2d8eb1b40606a9fe8d03296889b8 - languageName: node - linkType: hard - -"abbrev@npm:^2.0.0": - version: 2.0.0 - resolution: "abbrev@npm:2.0.0" - checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 - languageName: node - linkType: hard - -"acorn-walk@npm:^8.1.1": - version: 8.2.0 - resolution: "acorn-walk@npm:8.2.0" - checksum: 10c0/dbe92f5b2452c93e960c5594e666dd1fae141b965ff2cb4a1e1d0381e3e4db4274c5ce4ffa3d681a86ca2a8d4e29d5efc0670a08e23fd2800051ea387df56ca2 - languageName: node - linkType: hard - -"acorn@npm:^8.4.1": - version: 8.8.0 - resolution: "acorn@npm:8.8.0" - bin: - acorn: bin/acorn - checksum: 10c0/5efce4f59554e0ab766f32932cba34b86cc2ecdf24fcd27463beff41d8a1b1b9575c21f92c1b9f7f82b93374a9d5aed33c91f93e2d0cb1bdf3f1e06ec131e816 - languageName: node - linkType: hard - -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": - version: 7.1.1 - resolution: "agent-base@npm:7.1.1" - dependencies: - debug: "npm:^4.3.4" - checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: "npm:^2.0.0" - indent-string: "npm:^4.0.0" - checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 10c0/cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08 - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"arg@npm:^4.1.0": - version: 4.1.3 - resolution: "arg@npm:4.1.3" - checksum: 10c0/070ff801a9d236a6caa647507bdcc7034530604844d64408149a26b9e87c2f97650055c0f049abd1efc024b334635c01f29e0b632b371ac3f26130f4cf65997a - languageName: node - linkType: hard - -"assertion-error@npm:^1.1.0": - version: 1.1.0 - resolution: "assertion-error@npm:1.1.0" - checksum: 10c0/25456b2aa333250f01143968e02e4884a34588a8538fbbf65c91a637f1dbfb8069249133cd2f4e530f10f624d206a664e7df30207830b659e9f5298b00a4099b - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"cacache@npm:^18.0.0": - version: 18.0.4 - resolution: "cacache@npm:18.0.4" - dependencies: - "@npmcli/fs": "npm:^3.1.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^4.0.0" - ssri: "npm:^10.0.0" - tar: "npm:^6.1.11" - unique-filename: "npm:^3.0.0" - checksum: 10c0/6c055bafed9de4f3dcc64ac3dc7dd24e863210902b7c470eb9ce55a806309b3efff78033e3d8b4f7dcc5d467f2db43c6a2857aaaf26f0094b8a351d44c42179f - languageName: node - linkType: hard - -"chai@npm:^4.3.6": - version: 4.3.6 - resolution: "chai@npm:4.3.6" - dependencies: - assertion-error: "npm:^1.1.0" - check-error: "npm:^1.0.2" - deep-eql: "npm:^3.0.1" - get-func-name: "npm:^2.0.0" - loupe: "npm:^2.3.1" - pathval: "npm:^1.1.1" - type-detect: "npm:^4.0.5" - checksum: 10c0/7bcc2e72db775cf94853bf8deb481e47f83705b95bb67b13c32367b2f6913a55e9c24dea0d597027626412b928f28ccd4de7f7608aaeab12a6350c68529148c9 - languageName: node - linkType: hard - -"check-error@npm:^1.0.2": - version: 1.0.2 - resolution: "check-error@npm:1.0.2" - checksum: 10c0/c58ac4d6a92203209a61d025568198c073f101691eb6247f999266e1d1e3ab3af2bbe0a41af5008c1f1b95446ec7831e6ba91f03816177f2da852f316ad7921d - languageName: node - linkType: hard - -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 - languageName: node - linkType: hard - -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"create-require@npm:^1.1.0": - version: 1.1.1 - resolution: "create-require@npm:1.1.1" - checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.0": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 - languageName: node - linkType: hard - -"debug@npm:4": - version: 4.3.5 - resolution: "debug@npm:4.3.5" - dependencies: - ms: "npm:2.1.2" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/082c375a2bdc4f4469c99f325ff458adad62a3fc2c482d59923c260cb08152f34e2659f72b3767db8bb2f21ca81a60a42d1019605a412132d7b9f59363a005cc - languageName: node - linkType: hard - -"debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" - dependencies: - ms: "npm:2.1.2" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 - languageName: node - linkType: hard - -"deep-eql@npm:^3.0.1": - version: 3.0.1 - resolution: "deep-eql@npm:3.0.1" - dependencies: - type-detect: "npm:^4.0.0" - checksum: 10c0/80b33c1c7713b3d5db89e6b5e9b22050f39c8a88e12a015616da8391e013988790d045a5c612b0c6dc43cc4bec51eadbe0fcf6075cc9717f8f56efdb305b6e6f - languageName: node - linkType: hard - -"diff@npm:^4.0.1": - version: 4.0.2 - resolution: "diff@npm:4.0.2" - checksum: 10c0/81b91f9d39c4eaca068eb0c1eb0e4afbdc5bb2941d197f513dd596b820b956fef43485876226d65d497bebc15666aa2aa82c679e84f65d5f2bfbf14ee46e32c1 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"esbuild-android-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-android-64@npm:0.14.54" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"esbuild-android-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-android-arm64@npm:0.14.54" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-darwin-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-darwin-64@npm:0.14.54" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"esbuild-darwin-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-darwin-arm64@npm:0.14.54" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-freebsd-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-freebsd-64@npm:0.14.54" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-freebsd-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-freebsd-arm64@npm:0.14.54" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-linux-32@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-32@npm:0.14.54" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"esbuild-linux-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-64@npm:0.14.54" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"esbuild-linux-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-arm64@npm:0.14.54" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-linux-arm@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-arm@npm:0.14.54" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"esbuild-linux-mips64le@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-mips64le@npm:0.14.54" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"esbuild-linux-ppc64le@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-ppc64le@npm:0.14.54" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"esbuild-linux-riscv64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-riscv64@npm:0.14.54" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"esbuild-linux-s390x@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-linux-s390x@npm:0.14.54" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"esbuild-netbsd-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-netbsd-64@npm:0.14.54" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-openbsd-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-openbsd-64@npm:0.14.54" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-sunos-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-sunos-64@npm:0.14.54" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"esbuild-windows-32@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-windows-32@npm:0.14.54" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"esbuild-windows-64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-windows-64@npm:0.14.54" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"esbuild-windows-arm64@npm:0.14.54": - version: 0.14.54 - resolution: "esbuild-windows-arm64@npm:0.14.54" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"esbuild@npm:^0.14.47": - version: 0.14.54 - resolution: "esbuild@npm:0.14.54" - dependencies: - "@esbuild/linux-loong64": "npm:0.14.54" - esbuild-android-64: "npm:0.14.54" - esbuild-android-arm64: "npm:0.14.54" - esbuild-darwin-64: "npm:0.14.54" - esbuild-darwin-arm64: "npm:0.14.54" - esbuild-freebsd-64: "npm:0.14.54" - esbuild-freebsd-arm64: "npm:0.14.54" - esbuild-linux-32: "npm:0.14.54" - esbuild-linux-64: "npm:0.14.54" - esbuild-linux-arm: "npm:0.14.54" - esbuild-linux-arm64: "npm:0.14.54" - esbuild-linux-mips64le: "npm:0.14.54" - esbuild-linux-ppc64le: "npm:0.14.54" - esbuild-linux-riscv64: "npm:0.14.54" - esbuild-linux-s390x: "npm:0.14.54" - esbuild-netbsd-64: "npm:0.14.54" - esbuild-openbsd-64: "npm:0.14.54" - esbuild-sunos-64: "npm:0.14.54" - esbuild-windows-32: "npm:0.14.54" - esbuild-windows-64: "npm:0.14.54" - esbuild-windows-arm64: "npm:0.14.54" - dependenciesMeta: - "@esbuild/linux-loong64": - optional: true - esbuild-android-64: - optional: true - esbuild-android-arm64: - optional: true - esbuild-darwin-64: - optional: true - esbuild-darwin-arm64: - optional: true - esbuild-freebsd-64: - optional: true - esbuild-freebsd-arm64: - optional: true - esbuild-linux-32: - optional: true - esbuild-linux-64: - optional: true - esbuild-linux-arm: - optional: true - esbuild-linux-arm64: - optional: true - esbuild-linux-mips64le: - optional: true - esbuild-linux-ppc64le: - optional: true - esbuild-linux-riscv64: - optional: true - esbuild-linux-s390x: - optional: true - esbuild-netbsd-64: - optional: true - esbuild-openbsd-64: - optional: true - esbuild-sunos-64: - optional: true - esbuild-windows-32: - optional: true - esbuild-windows-64: - optional: true - esbuild-windows-arm64: - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/1df3cf7c5175ebee284fd027f287385a07ce8a0f0460a4412881aeff707577d91e55302f220ee8397b3b5aa17f4ceeb80eac16f36fc676532ff1b744e5965f2d - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.1 - resolution: "exponential-backoff@npm:3.1.1" - checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.2.1 - resolution: "foreground-child@npm:3.2.1" - dependencies: - cross-spawn: "npm:^7.0.0" - signal-exit: "npm:^4.0.1" - checksum: 10c0/9a53a33dbd87090e9576bef65fb4a71de60f6863a8062a7b11bc1cbe3cc86d428677d7c0b9ef61cdac11007ac580006f78bd5638618d564cfd5e6fd713d6878f - languageName: node - linkType: hard - -"fs-minipass@npm:^2.0.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fsevents@npm:~2.3.2": - version: 2.3.2 - resolution: "fsevents@npm:2.3.2" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/be78a3efa3e181cda3cf7a4637cb527bcebb0bd0ea0440105a3bb45b86f9245b307dc10a2507e8f4498a7d4ec349d1910f4d73e4d4495b16103106e07eee735b - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": - version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: 10c0/60b74b2407e1942e1ed7f8c284f8ef714d0689dcfce5319985a5b7da3fc727f40b4a59ec72dc55aa83365ad7b8fa4fac3a30d93c850a2b452f29ae03dbc10a1e - languageName: node - linkType: hard - -"get-func-name@npm:^2.0.0": - version: 2.0.0 - resolution: "get-func-name@npm:2.0.0" - checksum: 10c0/ed8791f7ba92cfd747259dff7ec8b6cc42734cebd031fb58c99a6e71d24d3532d84b46ad7806cafad6ad21784dd04ae1808a002d2b21001425e21f5f394c34e7 - languageName: node - linkType: hard - -"glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: "npm:^1.1.1" - checksum: 10c0/e1da0d2bd109f116b632f27782cf23182b42f14972ca9540e4c5aa7e52647407a0a4a76937334fddcb56befe94a3494825ec22b19b51f5e5507c3153fd1a5e1b - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.5 - resolution: "https-proxy-agent@npm:7.0.5" - dependencies: - agent-base: "npm:^7.0.2" - debug: "npm:4" - checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"is-core-module@npm:^2.9.0": - version: 2.10.0 - resolution: "is-core-module@npm:2.10.0" - dependencies: - has: "npm:^1.0.3" - checksum: 10c0/af7c3b24cb3375688a84306dcfa71c9305fd03af6548aaeb51ed345f85abafe22e071835b3a5f4bb1e87b434404410ec31ee45749f617a7acf2a4dcb9f677ae7 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"local-pkg@npm:^0.4.2": - version: 0.4.2 - resolution: "local-pkg@npm:0.4.2" - checksum: 10c0/85f4463d7b29b19cca8c71e0d02c486fb98b5fdb0c1f5ec73e2fb984e9d35119cd88996ac8ef86f9b0d9865785fc4ccdcd1207f76c028cb27b76f398b9bbba2a - languageName: node - linkType: hard - -"loupe@npm:^2.3.1": - version: 2.3.4 - resolution: "loupe@npm:2.3.4" - dependencies: - get-func-name: "npm:^2.0.0" - checksum: 10c0/a48a97f7be1fe0ec28dc53fce366e44b9440b5781b7175727f397c3096b379986dc1d08c5e2b0bc50f34ba2e6836684a6b222e9bc26765c1e97368df80afe459 - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - -"make-error@npm:^1.1.1": - version: 1.3.6 - resolution: "make-error@npm:1.3.6" - checksum: 10c0/171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f - languageName: node - linkType: hard - -"make-fetch-happen@npm:^13.0.0": - version: 13.0.1 - resolution: "make-fetch-happen@npm:13.0.1" - dependencies: - "@npmcli/agent": "npm:^2.0.0" - cacache: "npm:^18.0.0" - http-cache-semantics: "npm:^4.1.1" - is-lambda: "npm:^1.0.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^3.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^0.6.3" - proc-log: "npm:^4.2.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^10.0.0" - checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e - languageName: node - linkType: hard - -"minimatch@npm:^9.0.4": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^3.0.0": - version: 3.0.5 - resolution: "minipass-fetch@npm:3.0.5" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^2.1.2" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 - languageName: node - linkType: hard - -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: "npm:^3.0.0" - yallist: "npm:^4.0.0" - checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 - languageName: node - linkType: hard - -"mkdirp@npm:^1.0.3": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf - languageName: node - linkType: hard - -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc - languageName: node - linkType: hard - -"nanoid@npm:^3.3.4": - version: 3.3.4 - resolution: "nanoid@npm:3.3.4" - bin: - nanoid: bin/nanoid.cjs - checksum: 10c0/a0747d5c6021828fe8d38334e5afb05d3268d7d4b06024058ec894ccc47070e4e81d268a6b75488d2ff3485fa79a75c251d4b7c6f31051bb54bb662b6fd2a27d - languageName: node - linkType: hard - -"negotiator@npm:^0.6.3": - version: 0.6.3 - resolution: "negotiator@npm:0.6.3" - checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 10.2.0 - resolution: "node-gyp@npm:10.2.0" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^13.0.0" - nopt: "npm:^7.0.0" - proc-log: "npm:^4.1.0" - semver: "npm:^7.3.5" - tar: "npm:^6.2.1" - which: "npm:^4.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/00630d67dbd09a45aee0a5d55c05e3916ca9e6d427ee4f7bc392d2d3dc5fad7449b21fc098dd38260a53d9dcc9c879b36704a1994235d4707e7271af7e9a835b - languageName: node - linkType: hard - -"nopt@npm:^7.0.0": - version: 7.2.1 - resolution: "nopt@npm:7.2.1" - dependencies: - abbrev: "npm:^2.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 - languageName: node - linkType: hard - -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: "npm:^3.0.0" - checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 - languageName: node - linkType: hard - -"package-json-from-dist@npm:^1.0.0": - version: 1.0.0 - resolution: "package-json-from-dist@npm:1.0.0" - checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033 - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"pathval@npm:^1.1.1": - version: 1.1.1 - resolution: "pathval@npm:1.1.1" - checksum: 10c0/f63e1bc1b33593cdf094ed6ff5c49c1c0dc5dc20a646ca9725cc7fe7cd9995002d51d5685b9b2ec6814342935748b711bafa840f84c0bb04e38ff40a335c94dc - languageName: node - linkType: hard - -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: 10c0/20a5b249e331c14479d94ec6817a182fd7a5680debae82705747b2db7ec50009a5f6648d0621c561b0572703f84dbef0858abcbd5856d3c5511426afcb1961f7 - languageName: node - linkType: hard - -"postcss@npm:^8.4.16": - version: 8.4.16 - resolution: "postcss@npm:8.4.16" - dependencies: - nanoid: "npm:^3.3.4" - picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.0.2" - checksum: 10c0/971e10b5492ffce3d30e39ffba1b4f135d0c751bf774493babe4cb89ddb4995aabb2ce290f48bbf1d9ae60016a6ad492535e614b22b15322f977c7744e800fa2 - languageName: node - linkType: hard - -"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": - version: 4.2.0 - resolution: "proc-log@npm:4.2.0" - checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"resolve@npm:^1.22.1": - version: 1.22.1 - resolution: "resolve@npm:1.22.1" - dependencies: - is-core-module: "npm:^2.9.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/6d58b1cb40f3fc80b9e45dd799d84cdc3829a993e4b9fa3b59d331e1dfacd0870e1851f4d0eb549d68c796e0b7087b43d1aec162653ccccff9e18191221a6e7d - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^1.22.1#optional!builtin": - version: 1.22.1 - resolution: "resolve@patch:resolve@npm%3A1.22.1#optional!builtin::version=1.22.1&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.9.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/0d8ccceba5537769c42aa75e4aa75ae854aac866a11d7e9ffdb1663f0158ee646a0d48fc2818ed5e7fb364d64220a1fb9092a160e11e00cbdd5fbab39a13092c - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"rollup@npm:>=2.75.6 <2.77.0 || ~2.77.0": - version: 2.77.3 - resolution: "rollup@npm:2.77.3" - dependencies: - fsevents: "npm:~2.3.2" - dependenciesMeta: - fsevents: - optional: true - bin: - rollup: dist/bin/rollup - checksum: 10c0/7e04ba4e8fdbc3a4a368013e4b788044c16fe94e7301aacbf38e37210983e159b97887ddd3333be9f78fedb30264f094c111ff56a0207c21d4e1745248a7aa42 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"semver@npm:^7.3.5": - version: 7.6.2 - resolution: "semver@npm:7.6.2" - bin: - semver: bin/semver.js - checksum: 10c0/97d3441e97ace8be4b1976433d1c32658f6afaff09f143e52c593bae7eef33de19e3e369c88bd985ce1042c6f441c80c6803078d1de2a9988080b66684cbb30c - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.4 - resolution: "socks-proxy-agent@npm:8.0.4" - dependencies: - agent-base: "npm:^7.1.1" - debug: "npm:^4.3.4" - socks: "npm:^2.8.3" - checksum: 10c0/345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a - languageName: node - linkType: hard - -"socks@npm:^2.8.3": - version: 2.8.3 - resolution: "socks@npm:2.8.3" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 - languageName: node - linkType: hard - -"source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: 10c0/32f2dfd1e9b7168f9a9715eb1b4e21905850f3b50cf02cf476e47e4eebe8e6b762b63a64357896aa29b37e24922b4282df0f492e0d2ace572b43d15525976ff8 - languageName: node - linkType: hard - -"spec@workspace:.": - version: 0.0.0-use.local - resolution: "spec@workspace:." - dependencies: - "@types/node": "npm:^18.0.3" - ts-node: "npm:^10.8.2" - typescript: "npm:^4.7.4" - vite: "npm:^3.0.9" - vitest: "npm:^0.22.1" - languageName: unknown - linkType: soft - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"ssri@npm:^10.0.0": - version: 10.0.6 - resolution: "ssri@npm:10.0.6" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 - languageName: node - linkType: hard - -"tar@npm:^6.1.11, tar@npm:^6.2.1": - version: 6.2.1 - resolution: "tar@npm:6.2.1" - dependencies: - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.0.0" - minipass: "npm:^5.0.0" - minizlib: "npm:^2.1.1" - mkdirp: "npm:^1.0.3" - yallist: "npm:^4.0.0" - checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 - languageName: node - linkType: hard - -"tinypool@npm:^0.2.4": - version: 0.2.4 - resolution: "tinypool@npm:0.2.4" - checksum: 10c0/9d705ef2a623d4a2e263dec3bb292d390d83cd7db65d77a030e0f988866f36584802190ca2bc9083b028dee5c06253c6fb4872d52d0f0a9361d77f63b0be968d - languageName: node - linkType: hard - -"tinyspy@npm:^1.0.2": - version: 1.0.2 - resolution: "tinyspy@npm:1.0.2" - checksum: 10c0/349b574b4f7f359ee7d6c99089ab3148291a94cf3143335f21581df68d183d1582ae703021a02ba376fb98aa0749d76445e5d98acee501f123b04b9da760fea1 - languageName: node - linkType: hard - -"ts-node@npm:^10.8.2": - version: 10.9.1 - resolution: "ts-node@npm:10.9.1" - dependencies: - "@cspotcode/source-map-support": "npm:^0.8.0" - "@tsconfig/node10": "npm:^1.0.7" - "@tsconfig/node12": "npm:^1.0.7" - "@tsconfig/node14": "npm:^1.0.0" - "@tsconfig/node16": "npm:^1.0.2" - acorn: "npm:^8.4.1" - acorn-walk: "npm:^8.1.1" - arg: "npm:^4.1.0" - create-require: "npm:^1.1.0" - diff: "npm:^4.0.1" - make-error: "npm:^1.1.1" - v8-compile-cache-lib: "npm:^3.0.1" - yn: "npm:3.1.1" - peerDependencies: - "@swc/core": ">=1.2.50" - "@swc/wasm": ">=1.2.50" - "@types/node": "*" - typescript: ">=2.7" - peerDependenciesMeta: - "@swc/core": - optional: true - "@swc/wasm": - optional: true - bin: - ts-node: dist/bin.js - ts-node-cwd: dist/bin-cwd.js - ts-node-esm: dist/bin-esm.js - ts-node-script: dist/bin-script.js - ts-node-transpile-only: dist/bin-transpile.js - ts-script: dist/bin-script-deprecated.js - checksum: 10c0/95187932fb83f3901e22546bd2feeac7d2feb4f412f42ac3a595f049a23e8dcf70516dffb51866391228ea2dbcfaea039e250fb2bb334d48a86ab2b6aea0ae2d - languageName: node - linkType: hard - -"type-detect@npm:^4.0.0, type-detect@npm:^4.0.5": - version: 4.0.8 - resolution: "type-detect@npm:4.0.8" - checksum: 10c0/8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd - languageName: node - linkType: hard - -"typescript@npm:^4.7.4": - version: 4.7.4 - resolution: "typescript@npm:4.7.4" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/8c1c4007b6ce5b24c49f0e89173ab9e82687cc6ae54418d1140bb63b82d6598d085ac0f993fe3d3d1fbf87a2c76f1f81d394dc76315bc72c7a9f8561c5d8d205 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^4.7.4#optional!builtin": - version: 4.7.4 - resolution: "typescript@patch:typescript@npm%3A4.7.4#optional!builtin::version=4.7.4&hash=65a307" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/2eb6e31b04fabec84a4d07b5d567deb5ef0a2971d89d9adb16895f148f7d8508adfb12074abc2efc6966805d3664e68ab67925060e5b0ebd8da616db4b151906 - languageName: node - linkType: hard - -"unique-filename@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-filename@npm:3.0.0" - dependencies: - unique-slug: "npm:^4.0.0" - checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f - languageName: node - linkType: hard - -"unique-slug@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-slug@npm:4.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 - languageName: node - linkType: hard - -"v8-compile-cache-lib@npm:^3.0.1": - version: 3.0.1 - resolution: "v8-compile-cache-lib@npm:3.0.1" - checksum: 10c0/bdc36fb8095d3b41df197f5fb6f11e3a26adf4059df3213e3baa93810d8f0cc76f9a74aaefc18b73e91fe7e19154ed6f134eda6fded2e0f1c8d2272ed2d2d391 - languageName: node - linkType: hard - -"vite@npm:^2.9.12 || ^3.0.0-0, vite@npm:^3.0.9": - version: 3.0.9 - resolution: "vite@npm:3.0.9" - dependencies: - esbuild: "npm:^0.14.47" - fsevents: "npm:~2.3.2" - postcss: "npm:^8.4.16" - resolve: "npm:^1.22.1" - rollup: "npm:>=2.75.6 <2.77.0 || ~2.77.0" - peerDependencies: - less: "*" - sass: "*" - stylus: "*" - terser: ^5.4.0 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - less: - optional: true - sass: - optional: true - stylus: - optional: true - terser: - optional: true - bin: - vite: bin/vite.js - checksum: 10c0/0e39c11e8befd9ac139ab48ace83125bb4ad0ded14fd7c370290af8c001accbb5e67ce7677d958f5b2ffaf0a38b342ffabf166bc33aa5de32a8510ecb4596be9 - languageName: node - linkType: hard - -"vitest@npm:^0.22.1": - version: 0.22.1 - resolution: "vitest@npm:0.22.1" - dependencies: - "@types/chai": "npm:^4.3.3" - "@types/chai-subset": "npm:^1.3.3" - "@types/node": "npm:*" - chai: "npm:^4.3.6" - debug: "npm:^4.3.4" - local-pkg: "npm:^0.4.2" - tinypool: "npm:^0.2.4" - tinyspy: "npm:^1.0.2" - vite: "npm:^2.9.12 || ^3.0.0-0" - peerDependencies: - "@edge-runtime/vm": "*" - "@vitest/browser": "*" - "@vitest/ui": "*" - happy-dom: "*" - jsdom: "*" - peerDependenciesMeta: - "@edge-runtime/vm": - optional: true - "@vitest/browser": - optional: true - "@vitest/ui": - optional: true - happy-dom: - optional: true - jsdom: - optional: true - bin: - vitest: vitest.mjs - checksum: 10c0/944d50ca7368636a20a49c22d3c9e217e5312f3531bee7ae2ec3cf70e06e83fdb79d991cd586bbacce7a2b11e28a27d4d01b6a8665fb7372f6844eeef9ee493b - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^4.0.0": - version: 4.0.0 - resolution: "which@npm:4.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yn@npm:3.1.1": - version: 3.1.1 - resolution: "yn@npm:3.1.1" - checksum: 10c0/0732468dd7622ed8a274f640f191f3eaf1f39d5349a1b72836df484998d7d9807fbea094e2f5486d6b0cd2414aad5775972df0e68f8604db89a239f0f4bf7443 - languageName: node - linkType: hard From a1a0afc585e870ef4084a113f03b9a485e66d265 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 16:21:13 +0900 Subject: [PATCH 026/139] refactor: Reduced the memory size of structure field --- src/server.rs | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/server.rs b/src/server.rs index 1e41eba..d79c862 100644 --- a/src/server.rs +++ b/src/server.rs @@ -31,6 +31,7 @@ use lsp_types::WorkDoneProgressBegin; use lsp_types::WorkDoneProgressCreateParams; use lsp_types::WorkDoneProgressEnd; use lsp_types::WorkDoneProgressOptions; +use lsp_types::WorkspaceFolder; use serde::de::Error; use serde::Deserialize; use serde_json::json; @@ -51,7 +52,7 @@ pub struct InitializedOptions { } pub struct TestingLS { - pub initialize_params: InitializeParams, + pub workspace_folders: Option>, pub options: InitializedOptions, pub workspaces_cache: Vec, } @@ -65,7 +66,7 @@ impl Default for TestingLS { impl TestingLS { pub fn new() -> Self { Self { - initialize_params: Default::default(), + workspace_folders: None, options: Default::default(), workspaces_cache: Vec::new(), } @@ -77,7 +78,6 @@ impl TestingLS { Ok(cwd) } else { let default_project_dir = self - .initialize_params .workspace_folders .as_ref() .ok_or(LSError::Any(anyhow::anyhow!("No workspace folders found")))?; @@ -137,9 +137,10 @@ impl TestingLS { if let Some(method) = method { match *method { "initialize" => { - self.initialize_params = InitializeParams::deserialize(params)?; + let initialize_params = InitializeParams::deserialize(params)?; + self.workspace_folders = initialize_params.workspace_folders; self.options = (self.handle_initialization_options( - self.initialize_params.initialization_options.as_ref(), + initialize_params.initialization_options.as_ref(), ))?; let id = value["id"].as_i64().unwrap(); self.initialize(id)?; @@ -579,13 +580,10 @@ mod tests { fn test_check_file() { let abs_path_of_demo = std::env::current_dir().unwrap().join("demo/rust"); let mut server = TestingLS { - initialize_params: InitializeParams { - workspace_folders: Some(vec![WorkspaceFolder { - uri: Url::from_file_path(&abs_path_of_demo).unwrap(), - name: "demo".to_string(), - }]), - ..InitializeParams::default() - }, + workspace_folders: Some(vec![WorkspaceFolder { + uri: Url::from_file_path(&abs_path_of_demo).unwrap(), + name: "demo".to_string(), + }]), options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![])]), }, @@ -611,13 +609,10 @@ mod tests { ..Default::default() }; let mut server = TestingLS { - initialize_params: InitializeParams { - workspace_folders: Some(vec![WorkspaceFolder { - uri: Url::from_file_path(abs_path_of_demo.clone()).unwrap(), - name: "demo".to_string(), - }]), - ..InitializeParams::default() - }, + workspace_folders: Some(vec![WorkspaceFolder { + uri: Url::from_file_path(&abs_path_of_demo).unwrap(), + name: "demo".to_string(), + }]), options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![adapter_conf])]), }, @@ -678,13 +673,10 @@ mod tests { TestingLS::project_files(&abs_path_of_demo.clone(), &["/**/*.rs".to_string()], &[]); let server = TestingLS { - initialize_params: InitializeParams { - workspace_folders: Some(vec![WorkspaceFolder { - uri: Url::from_file_path(&abs_path_of_demo).unwrap(), - name: "demo".to_string(), - }]), - ..InitializeParams::default() - }, + workspace_folders: Some(vec![WorkspaceFolder { + uri: Url::from_file_path(&abs_path_of_demo).unwrap(), + name: "demo".to_string(), + }]), options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![adapter_conf.clone()])]), }, From 8ecf8891f83707c10ef15d2765d33fb466fd2723 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 16:29:32 +0900 Subject: [PATCH 027/139] feat: consolidate duplicate code into functions --- src/server.rs | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/server.rs b/src/server.rs index d79c862..e2a75c3 100644 --- a/src/server.rs +++ b/src/server.rs @@ -149,35 +149,23 @@ impl TestingLS { self.diagnose_workspace()?; } "textDocument/diagnostic" | "textDocument/didSave" => { - let uri = params["textDocument"]["uri"] - .as_str() - .ok_or(serde_json::Error::custom("`textDocument.uri` is not set"))?; - let uri = &format_uri(uri); - self.check_file(uri, false)?; + let uri = self.extract_textdocument_uri(¶ms["uri"])?; + self.check_file(&uri, false)?; } "textDocument/didOpen" => { - let uri = params["textDocument"]["uri"] - .as_str() - .ok_or(serde_json::Error::custom("`textDocument.uri` is not set"))?; - let uri = &format_uri(uri); - if self.refreshing_needed(uri) { + let uri = self.extract_textdocument_uri(¶ms["uri"])?; + if self.refreshing_needed(&uri) { self.refresh_workspaces_cache()?; } } "$/runFileTest" => { - let uri = params["uri"] - .as_str() - .ok_or(serde_json::Error::custom("`uri` is not set"))?; - let uri = &format_uri(uri); - self.check_file(uri, false)?; + let uri = self.extract_uri(¶ms["uri"])?; + self.check_file(&uri, false)?; } "$/discoverFileTest" => { let id = value["id"].as_i64().unwrap(); - let uri = params["uri"] - .as_str() - .ok_or(serde_json::Error::custom("`uri` is not set"))?; - let uri = &format_uri(uri); - let result = self.discover_file(uri)?; + let uri = self.extract_uri(¶ms["uri"])?; + let result = self.discover_file(&uri)?; send_stdout(&json!({ "jsonrpc": "2.0", "id": id, @@ -190,6 +178,20 @@ impl TestingLS { } } + fn extract_textdocument_uri(&self, params: &Value) -> Result { + let uri = params["textDocument"]["uri"] + .as_str() + .ok_or(serde_json::Error::custom("`textDocument.uri` is not set"))?; + Ok(format_uri(uri)) + } + + fn extract_uri(&self, params: &Value) -> Result { + let uri = params["uri"] + .as_str() + .ok_or(serde_json::Error::custom("`uri` is not set"))?; + Ok(format_uri(uri)) + } + fn adapter_commands(&self) -> HashMap> { self.options.adapter_command.clone() } From 65e95494bd0e72ad5b22aad65ff86acbfd9f34d9 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 16:58:34 +0900 Subject: [PATCH 028/139] refactor: move some functions for main loop to main.rs --- src/main.rs | 113 +++++++++++++++++++++++++++++++- src/server.rs | 176 +++++++------------------------------------------- 2 files changed, 137 insertions(+), 152 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3cebd00..155d8a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,13 +4,124 @@ mod server; mod spec; mod util; +use std::io::{self, BufRead, Read}; + +use error::LSError; +use lsp_types::InitializeParams; +use serde::de::Error; +use serde::Deserialize; +use serde_json::{json, Value}; +use util::{format_uri, send_stdout}; + use crate::log::Log; use crate::server::TestingLS; +fn extract_textdocument_uri(params: &Value) -> Result { + let uri = params["textDocument"]["uri"] + .as_str() + .ok_or(serde_json::Error::custom("`textDocument.uri` is not set"))?; + Ok(format_uri(uri)) +} + +fn extract_uri(params: &Value) -> Result { + let uri = params["uri"] + .as_str() + .ok_or(serde_json::Error::custom("`uri` is not set"))?; + Ok(format_uri(uri)) +} + +fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { + loop { + let mut size = 0; + 'read_header: loop { + let mut buffer = String::new(); + let stdin = io::stdin(); + let mut handle = stdin.lock(); // We get `StdinLock` here. + handle.read_line(&mut buffer)?; + + if buffer.is_empty() { + tracing::warn!("buffer is empty") + } + + // The end of header section + if buffer == "\r\n" { + break 'read_header; + } + + let splitted: Vec<&str> = buffer.split(' ').collect(); + + if splitted.len() != 2 { + tracing::warn!("unexpected"); + } + + let header_name = splitted[0].to_lowercase(); + let header_value = splitted[1].trim(); + + match header_name.as_ref() { + "content-length" => {} + "content-type:" => {} + _ => {} + } + + size = header_value.parse::().unwrap(); + } + + let stdin = io::stdin(); + let mut handle = stdin.lock(); + let mut buf = vec![0u8; size]; + handle.read_exact(&mut buf).unwrap(); + let message = String::from_utf8(buf).unwrap(); + + let value: Value = serde_json::from_str(&message)?; + let method = &value["method"].as_str(); + tracing::info!("method={:#?}", method); + let params = &value["params"]; + tracing::info!("params={:#?}", params); + + if let Some(method) = method { + match *method { + "initialize" => { + let initialize_params = InitializeParams::deserialize(params)?; + let id = value["id"].as_i64().unwrap(); + server.initialize(id, initialize_params)?; + } + "workspace/diagnostic" => { + server.diagnose_workspace()?; + } + "textDocument/diagnostic" | "textDocument/didSave" => { + let uri = extract_textdocument_uri(¶ms["uri"])?; + server.check_file(&uri, false)?; + } + "textDocument/didOpen" => { + let uri = extract_textdocument_uri(¶ms["uri"])?; + if server.refreshing_needed(&uri) { + server.refresh_workspaces_cache()?; + } + } + "$/runFileTest" => { + let uri = extract_uri(¶ms["uri"])?; + server.check_file(&uri, false)?; + } + "$/discoverFileTest" => { + let id = value["id"].as_i64().unwrap(); + let uri = extract_uri(¶ms["uri"])?; + let result = server.discover_file(&uri)?; + send_stdout(&json!({ + "jsonrpc": "2.0", + "id": id, + "result": result, + }))?; + } + _ => {} + } + } + } +} + fn main() { let mut server = TestingLS::new(); let _guard = Log::init().expect("Failed to initialize logger"); - if let Err(ls_error) = server.main_loop() { + if let Err(ls_error) = main_loop(&mut server) { tracing::error!("Error: {:?}", ls_error); } } diff --git a/src/server.rs b/src/server.rs index e2a75c3..daa3d9f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,45 +1,14 @@ use crate::error::LSError; -use crate::spec::AdapterConfiguration; -use crate::spec::AdapterId; -use crate::spec::DetectWorkspaceResult; -use crate::spec::DiscoverResult; -use crate::spec::RunFileTestResult; -use crate::spec::RunFileTestResultItem; -use crate::spec::WorkspaceAnalysis; -use crate::util::format_uri; +use crate::spec::*; use crate::util::resolve_path; use crate::util::send_stdout; use glob::Pattern; -use lsp_types::Diagnostic; -use lsp_types::DiagnosticOptions; -use lsp_types::DiagnosticServerCapabilities; -use lsp_types::DiagnosticSeverity; -use lsp_types::InitializeParams; -use lsp_types::InitializeResult; -use lsp_types::NumberOrString; -use lsp_types::Position; -use lsp_types::ProgressParams; -use lsp_types::ProgressParamsValue; -use lsp_types::PublishDiagnosticsParams; -use lsp_types::Range; -use lsp_types::ServerCapabilities; -use lsp_types::TextDocumentSyncCapability; -use lsp_types::TextDocumentSyncKind; -use lsp_types::Url; -use lsp_types::WorkDoneProgress; -use lsp_types::WorkDoneProgressBegin; -use lsp_types::WorkDoneProgressCreateParams; -use lsp_types::WorkDoneProgressEnd; -use lsp_types::WorkDoneProgressOptions; -use lsp_types::WorkspaceFolder; -use serde::de::Error; +use lsp_types::*; use serde::Deserialize; use serde_json::json; use serde_json::Value; use std::collections::HashMap; use std::env::current_dir; -use std::io::BufRead; -use std::io::{self, Read}; use std::path::Path; use std::path::PathBuf; use std::process::Command; @@ -49,6 +18,7 @@ use std::process::Output; #[serde(rename_all = "camelCase")] pub struct InitializedOptions { adapter_command: HashMap>, + enable_workspace_diagnostics: Option, } pub struct TestingLS { @@ -86,110 +56,26 @@ impl TestingLS { } } - pub fn main_loop(&mut self) -> Result<(), LSError> { - loop { - let mut size = 0; - 'read_header: loop { - let mut buffer = String::new(); - let stdin = io::stdin(); - let mut handle = stdin.lock(); // We get `StdinLock` here. - handle.read_line(&mut buffer)?; + pub fn initialize( + &mut self, + id: i64, + initialize_params: InitializeParams, + ) -> Result<(), LSError> { + self.workspace_folders = initialize_params.workspace_folders; + self.options = (self + .handle_initialization_options(initialize_params.initialization_options.as_ref()))?; + let result = InitializeResult { + capabilities: self.build_capabilities(), + ..InitializeResult::default() + }; - if buffer.is_empty() { - tracing::warn!("buffer is empty") - } + send_stdout(&json!({ + "jsonrpc": "2.0", + "id": id, + "result": result, + }))?; - // The end of header section - if buffer == "\r\n" { - break 'read_header; - } - - let splitted: Vec<&str> = buffer.split(' ').collect(); - - if splitted.len() != 2 { - tracing::warn!("unexpected"); - } - - let header_name = splitted[0].to_lowercase(); - let header_value = splitted[1].trim(); - - match header_name.as_ref() { - "content-length" => {} - "content-type:" => {} - _ => {} - } - - size = header_value.parse::().unwrap(); - } - - let stdin = io::stdin(); - let mut handle = stdin.lock(); - let mut buf = vec![0u8; size]; - handle.read_exact(&mut buf).unwrap(); - let message = String::from_utf8(buf).unwrap(); - - let value: Value = serde_json::from_str(&message)?; - let method = &value["method"].as_str(); - tracing::info!("method={:#?}", method); - let params = &value["params"]; - tracing::info!("params={:#?}", params); - - if let Some(method) = method { - match *method { - "initialize" => { - let initialize_params = InitializeParams::deserialize(params)?; - self.workspace_folders = initialize_params.workspace_folders; - self.options = (self.handle_initialization_options( - initialize_params.initialization_options.as_ref(), - ))?; - let id = value["id"].as_i64().unwrap(); - self.initialize(id)?; - } - "workspace/diagnostic" => { - self.diagnose_workspace()?; - } - "textDocument/diagnostic" | "textDocument/didSave" => { - let uri = self.extract_textdocument_uri(¶ms["uri"])?; - self.check_file(&uri, false)?; - } - "textDocument/didOpen" => { - let uri = self.extract_textdocument_uri(¶ms["uri"])?; - if self.refreshing_needed(&uri) { - self.refresh_workspaces_cache()?; - } - } - "$/runFileTest" => { - let uri = self.extract_uri(¶ms["uri"])?; - self.check_file(&uri, false)?; - } - "$/discoverFileTest" => { - let id = value["id"].as_i64().unwrap(); - let uri = self.extract_uri(¶ms["uri"])?; - let result = self.discover_file(&uri)?; - send_stdout(&json!({ - "jsonrpc": "2.0", - "id": id, - "result": result, - }))?; - } - _ => {} - } - } - } - } - - fn extract_textdocument_uri(&self, params: &Value) -> Result { - let uri = params["textDocument"]["uri"] - .as_str() - .ok_or(serde_json::Error::custom("`textDocument.uri` is not set"))?; - Ok(format_uri(uri)) - } - - fn extract_uri(&self, params: &Value) -> Result { - let uri = params["uri"] - .as_str() - .ok_or(serde_json::Error::custom("`uri` is not set"))?; - Ok(format_uri(uri)) + Ok(()) } fn adapter_commands(&self) -> HashMap> { @@ -254,21 +140,6 @@ impl TestingLS { } } - pub fn initialize(&self, id: i64) -> Result<(), LSError> { - let result = InitializeResult { - capabilities: self.build_capabilities(), - ..InitializeResult::default() - }; - - send_stdout(&json!({ - "jsonrpc": "2.0", - "id": id, - "result": result, - }))?; - - Ok(()) - } - pub fn refresh_workspaces_cache(&mut self) -> Result<(), LSError> { let adapter_commands = self.adapter_commands(); let project_dir = self.project_dir()?; @@ -517,7 +388,7 @@ impl TestingLS { } #[allow(clippy::for_kv_map)] - fn discover_file(&self, path: &str) -> Result { + pub fn discover_file(&self, path: &str) -> Result { let target_paths = vec![path.to_string()]; let mut result: DiscoverResult = vec![]; for WorkspaceAnalysis { @@ -588,6 +459,7 @@ mod tests { }]), options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![])]), + enable_workspace_diagnostics: Some(true), }, workspaces_cache: Vec::new(), }; @@ -617,6 +489,7 @@ mod tests { }]), options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![adapter_conf])]), + enable_workspace_diagnostics: Some(true), }, workspaces_cache: Vec::new(), }; @@ -681,6 +554,7 @@ mod tests { }]), options: InitializedOptions { adapter_command: HashMap::from([(String::from(".rs"), vec![adapter_conf.clone()])]), + enable_workspace_diagnostics: Some(true), }, workspaces_cache: Vec::new(), }; From 90be4e498f92a393bcf121b9995e9b2d8162caff Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 17:33:19 +0900 Subject: [PATCH 029/139] chore(adapter): change log file location --- crates/adapter/src/log.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/adapter/src/log.rs b/crates/adapter/src/log.rs index c409633..7eefa83 100644 --- a/crates/adapter/src/log.rs +++ b/crates/adapter/src/log.rs @@ -5,7 +5,7 @@ pub struct Log; impl Log { pub fn init() -> Result { let home_dir = dirs::home_dir().unwrap(); - let log_path = home_dir.join(".config/testing_ls_adapter/logs"); + let log_path = home_dir.join(".config/testing_language_server/adapter/logs"); let file_appender = tracing_appender::rolling::daily(log_path, "prefix.log"); let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); tracing_subscriber::fmt().with_writer(non_blocking).init(); From 8939558793af89be4d8aa3638f16fb2ac0e6cd1d Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 18:28:33 +0900 Subject: [PATCH 030/139] feat: add configuration to disable workspace diagnostics close #28 --- src/main.rs | 2 +- src/server.rs | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 155d8a3..0e9a411 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,7 +36,7 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { 'read_header: loop { let mut buffer = String::new(); let stdin = io::stdin(); - let mut handle = stdin.lock(); // We get `StdinLock` here. + let mut handle = stdin.lock(); handle.read_line(&mut buffer)?; if buffer.is_empty() { diff --git a/src/server.rs b/src/server.rs index daa3d9f..7df7fa3 100644 --- a/src/server.rs +++ b/src/server.rs @@ -33,6 +33,15 @@ impl Default for TestingLS { } } +/// The status of workspace diagnostics +/// - Skipped: Skip workspace diagnostics (when `enable_workspace_diagnostics` is false) +/// - Done: Finish workspace diagnostics (when `enable_workspace_diagnostics` is true) +#[derive(Debug, PartialEq, Eq)] +pub enum WorkspaceDiagnosticsStatus { + Skipped, + Done, +} + impl TestingLS { pub fn new() -> Self { Self { @@ -204,8 +213,11 @@ impl TestingLS { Ok(()) } - pub fn diagnose_workspace(&mut self) -> Result<(), LSError> { + pub fn diagnose_workspace(&mut self) -> Result { self.refresh_workspaces_cache()?; + if !self.options.enable_workspace_diagnostics.unwrap_or(false) { + return Ok(WorkspaceDiagnosticsStatus::Skipped); + } self.workspaces_cache.iter().for_each( |WorkspaceAnalysis { @@ -217,7 +229,7 @@ impl TestingLS { }) }, ); - Ok(()) + Ok(WorkspaceDiagnosticsStatus::Done) } pub fn refreshing_needed(&self, path: &str) -> bool { @@ -566,4 +578,21 @@ mod tests { assert_eq!(diagnostic.severity.unwrap(), DiagnosticSeverity::WARNING); assert!(diagnostic.message.contains("Cannot run test command:")); } + + #[test] + fn skip_workspace_diagnostics() { + let mut server = TestingLS { + workspace_folders: Some(vec![WorkspaceFolder { + uri: Url::from_file_path(current_dir().unwrap()).unwrap(), + name: "demo".to_string(), + }]), + options: InitializedOptions { + adapter_command: HashMap::new(), + enable_workspace_diagnostics: Some(false), + }, + workspaces_cache: Vec::new(), + }; + let status = server.diagnose_workspace().unwrap(); + assert_eq!(status, WorkspaceDiagnosticsStatus::Skipped); + } } From 10f3453cad1e189e8fdd1c91c4d698fe39188b65 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 18:29:57 +0900 Subject: [PATCH 031/139] chore: update coc-settings --- .vim/coc-settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json index d930726..1312f7e 100644 --- a/.vim/coc-settings.json +++ b/.vim/coc-settings.json @@ -12,6 +12,7 @@ } ] }, + "testing.enableWorkspaceDiagnostics": true, "testing.server.path": "testing-language-server", "testing.trace.server": "verbose" } From f1a10ceb28725220636e235d9b10e68db6e37b49 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 18:57:48 +0900 Subject: [PATCH 032/139] chore: update version --- Cargo.lock | 46 +++++++++++++++++++-------------------- Cargo.toml | 2 +- crates/adapter/Cargo.toml | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acc76be..05829ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -602,27 +602,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "testing-language-server" -version = "0.0.3" -dependencies = [ - "anyhow", - "clap", - "dirs", - "glob", - "globwalk", - "lsp-types", - "once_cell", - "regex", - "serde", - "serde_json", - "strum", - "thiserror", - "tracing", - "tracing-appender", - "tracing-subscriber", -] - [[package]] name = "testing-language-server" version = "0.0.3" @@ -645,9 +624,30 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "testing-language-server" +version = "0.0.4" +dependencies = [ + "anyhow", + "clap", + "dirs", + "glob", + "globwalk", + "lsp-types", + "once_cell", + "regex", + "serde", + "serde_json", + "strum", + "thiserror", + "tracing", + "tracing-appender", + "tracing-subscriber", +] + [[package]] name = "testing-ls-adapter" -version = "0.0.1" +version = "0.0.2" dependencies = [ "anyhow", "clap", @@ -657,7 +657,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "testing-language-server 0.0.3", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 47aadd8..0c433fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.3" +version = "0.0.4" edition = "2021" author = "Kodai Kabasawa " description = "LSP server for testing" diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 8b74dcc..29c6161 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.1" +version = "0.0.2" edition = "2021" description = "testing-language-server adapter" license = "MIT" From d3f3528c53ebd8ae2b0864f53b2b27a052860c1a Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 22:11:24 +0900 Subject: [PATCH 033/139] fix: detect namespace correctly fix #31 --- crates/adapter/src/runner/util.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index f266284..9195914 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -133,8 +133,8 @@ pub fn discover_with_treesitter( cursor.set_byte_range(tree.root_node().byte_range()); let source = source_code.as_bytes(); let matches = cursor.matches(&query, tree.root_node(), source); + let mut namespace = ""; for m in matches { - let mut namespace_name = ""; let mut test_start_position = Point::default(); let mut test_end_position = Point::default(); for capture in m.captures { @@ -144,17 +144,17 @@ pub fn discover_with_treesitter( let end_position = capture.node.end_position(); match capture_name { "namespace.name" => { - namespace_name = value; + namespace = value; } "test.definition" => { test_start_position = start_position; test_end_position = end_position; } "test.name" => { - let test_name = value; + let test_name = [namespace, value].join(":"); let test_item = TestItem { - id: format!("{}:{}", namespace_name, test_name), - name: test_name.to_string(), + id: test_name.clone(), + name: test_name, start_position: Range { start: Position { line: test_start_position.row as u32, From 7c5e365167c7ed109972d010e57dbc2beeac93f5 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 22:11:55 +0900 Subject: [PATCH 034/139] chore: update demo --- demo/rust/src/lib.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/demo/rust/src/lib.rs b/demo/rust/src/lib.rs index 16ee774..60b0199 100644 --- a/demo/rust/src/lib.rs +++ b/demo/rust/src/lib.rs @@ -25,4 +25,32 @@ mod tests { async fn tokio_test_fail() { assert!(false); } + + mod nested_namespace { + fn not_test() {} + + #[test] + fn success() { + assert!(true); + } + + #[test] + fn fail() { + assert!(false); + } + + mod nested_nested_namespace { + fn not_test() {} + + #[test] + fn success() { + assert!(true); + } + + #[test] + fn fail() { + assert!(false); + } + } + } } From 0f73fa2abd795e684fde798470e24b9cb58d9006 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 4 Aug 2024 22:21:16 +0900 Subject: [PATCH 035/139] fix(adapter): format test item name --- crates/adapter/src/runner/deno.rs | 6 +++--- crates/adapter/src/runner/jest.rs | 4 ++-- crates/adapter/src/runner/util.rs | 6 +++++- crates/adapter/src/runner/vitest.rs | 12 ++++++------ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index eb63ce6..812cd99 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -253,7 +253,7 @@ mod tests { test_items, vec![ TestItem { - id: String::from(":addTest"), + id: String::from("addTest"), name: String::from("addTest"), start_position: Range { start: Position { @@ -277,7 +277,7 @@ mod tests { } }, TestItem { - id: String::from(":fail1"), + id: String::from("fail1"), name: String::from("fail1"), start_position: Range { start: Position { @@ -301,7 +301,7 @@ mod tests { } }, TestItem { - id: String::from(":fail1"), + id: String::from("fail1"), name: String::from("fail1"), start_position: Range { start: Position { diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 379fa1d..126da43 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -255,8 +255,8 @@ mod tests { assert_eq!( test_items, vec![TestItem { - id: String::from(":fail"), - name: String::from("fail"), + id: String::from("index:fail"), + name: String::from("index:fail"), start_position: Range { start: Position { line: 1, diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index 9195914..eb97673 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -151,7 +151,11 @@ pub fn discover_with_treesitter( test_end_position = end_position; } "test.name" => { - let test_name = [namespace, value].join(":"); + let test_name = if namespace.is_empty() { + value.to_string() + } else { + [namespace, value].join(":") + }; let test_item = TestItem { id: test_name.clone(), name: test_name, diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 193b60b..3034e2c 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -213,8 +213,8 @@ mod tests { test_items, vec![ TestItem { - id: String::from(":pass"), - name: String::from("pass"), + id: "describe text:pass".to_string(), + name: "describe text:pass".to_string(), start_position: Range { start: Position { line: 4, @@ -222,7 +222,7 @@ mod tests { }, end: Position { line: 4, - character: MAX_CHAR_LENGTH + character: 10000 } }, end_position: Range { @@ -237,8 +237,8 @@ mod tests { } }, TestItem { - id: String::from(":fail"), - name: String::from("fail"), + id: "describe text:fail".to_string(), + name: "describe text:fail".to_string(), start_position: Range { start: Position { line: 8, @@ -246,7 +246,7 @@ mod tests { }, end: Position { line: 8, - character: MAX_CHAR_LENGTH + character: 10000 } }, end_position: Range { From 9c3b8719a2427e1c2c1a637d212a2cd7675c1162 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 5 Aug 2024 21:50:39 +0900 Subject: [PATCH 036/139] fix: enable workspace diagnostics by default --- src/server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.rs b/src/server.rs index 7df7fa3..8d4dfc9 100644 --- a/src/server.rs +++ b/src/server.rs @@ -215,7 +215,7 @@ impl TestingLS { pub fn diagnose_workspace(&mut self) -> Result { self.refresh_workspaces_cache()?; - if !self.options.enable_workspace_diagnostics.unwrap_or(false) { + if !self.options.enable_workspace_diagnostics.unwrap_or(true) { return Ok(WorkspaceDiagnosticsStatus::Skipped); } From f7e4ffac6f4f18a8d802f5f6543af7ba5d423ab2 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 5 Aug 2024 21:50:59 +0900 Subject: [PATCH 037/139] fix: prevent accessing to a non-existent field --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0e9a411..45aed38 100644 --- a/src/main.rs +++ b/src/main.rs @@ -89,11 +89,11 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { server.diagnose_workspace()?; } "textDocument/diagnostic" | "textDocument/didSave" => { - let uri = extract_textdocument_uri(¶ms["uri"])?; + let uri = extract_textdocument_uri(params)?; server.check_file(&uri, false)?; } "textDocument/didOpen" => { - let uri = extract_textdocument_uri(¶ms["uri"])?; + let uri = extract_textdocument_uri(params)?; if server.refreshing_needed(&uri) { server.refresh_workspaces_cache()?; } From ad00f2c764ea78a014adb3cb90545d5685835d25 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 5 Aug 2024 21:52:33 +0900 Subject: [PATCH 038/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05829ac..bebd362 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -626,7 +626,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.4" +version = "0.0.6" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index 0c433fa..7eb0097 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "testing-language-server" -version = "0.0.4" +version = "0.0.6" edition = "2021" -author = "Kodai Kabasawa " description = "LSP server for testing" license = "MIT" From 56c97a4780df9adb4b6411f92ebdf6233bc7acef Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 5 Aug 2024 22:26:35 +0900 Subject: [PATCH 039/139] chore(adapter): update version --- Cargo.lock | 49 ++++++++++++++++++++------------------- crates/adapter/Cargo.toml | 4 ++-- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bebd362..1629da4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -602,28 +602,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "testing-language-server" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c758bef61755c8ff356a26a92a33b2f9950f2fb90001d5ac0305cc28ab613fba" -dependencies = [ - "anyhow", - "clap", - "dirs", - "glob", - "lsp-types", - "once_cell", - "regex", - "serde", - "serde_json", - "strum", - "thiserror", - "tracing", - "tracing-appender", - "tracing-subscriber", -] - [[package]] name = "testing-language-server" version = "0.0.6" @@ -645,9 +623,32 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "testing-language-server" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad25ceae0685a3744fb8ac2b1e096cab4b9c30649344051d4c238e546871291" +dependencies = [ + "anyhow", + "clap", + "dirs", + "glob", + "globwalk", + "lsp-types", + "once_cell", + "regex", + "serde", + "serde_json", + "strum", + "thiserror", + "tracing", + "tracing-appender", + "tracing-subscriber", +] + [[package]] name = "testing-ls-adapter" -version = "0.0.2" +version = "0.0.3" dependencies = [ "anyhow", "clap", @@ -657,7 +658,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.0.3", + "testing-language-server 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 29c6161..9093de0 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.2" +version = "0.0.3" edition = "2021" description = "testing-language-server adapter" license = "MIT" @@ -8,7 +8,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -testing-language-server = "0.0.3" +testing-language-server = "0.0.6" lsp-types = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } From 319e3b69d810b472f975da574544d7b0477369a8 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 7 Aug 2024 00:11:19 +0900 Subject: [PATCH 040/139] fix:(adapter): change format of test item id and name --- crates/adapter/src/runner/jest.rs | 4 ++-- crates/adapter/src/runner/util.rs | 22 ++++++++++++++-------- crates/adapter/src/runner/vitest.rs | 8 ++++---- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 126da43..a926d24 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -255,8 +255,8 @@ mod tests { assert_eq!( test_items, vec![TestItem { - id: String::from("index:fail"), - name: String::from("index:fail"), + id: String::from("index::fail"), + name: String::from("index::fail"), start_position: Range { start: Position { line: 1, diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index eb97673..08b3c0d 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -52,10 +52,16 @@ pub fn detect_workspaces_from_file_paths( let workspace = detect_workspace_from_file(PathBuf::from_str(&file_path).unwrap(), file_names); if let Some(workspace) = workspace { - result_map - .entry(workspace) - .or_default() - .push(file_path.clone()); + if result_map + .get(&workspace) + .map(|v| !v.contains(&file_path)) + .unwrap_or(true) + { + result_map + .entry(workspace) + .or_default() + .push(file_path.clone()); + } } } result_map @@ -151,14 +157,14 @@ pub fn discover_with_treesitter( test_end_position = end_position; } "test.name" => { - let test_name = if namespace.is_empty() { + let test_id = if namespace.is_empty() { value.to_string() } else { - [namespace, value].join(":") + [namespace, value].join("::") }; let test_item = TestItem { - id: test_name.clone(), - name: test_name, + id: test_id.clone(), + name: test_id, start_position: Range { start: Position { line: test_start_position.row as u32, diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 3034e2c..1cb38ee 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -213,8 +213,8 @@ mod tests { test_items, vec![ TestItem { - id: "describe text:pass".to_string(), - name: "describe text:pass".to_string(), + id: "describe text::pass".to_string(), + name: "describe text::pass".to_string(), start_position: Range { start: Position { line: 4, @@ -237,8 +237,8 @@ mod tests { } }, TestItem { - id: "describe text:fail".to_string(), - name: "describe text:fail".to_string(), + id: "describe text::fail".to_string(), + name: "describe text::fail".to_string(), start_position: Range { start: Position { line: 8, From d08184358021e014dbc3a3d5c39d8ee784c80adb Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 16:32:05 +0900 Subject: [PATCH 041/139] refactor: add some comments --- src/spec.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/spec.rs b/src/spec.rs index a9418f1..e751759 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -12,6 +12,7 @@ pub enum AdapterCommands { DetectWorkspace(DetectWorkspaceArgs), } +/// Arguments for ` discover` command #[derive(clap::Args, Debug)] #[command(version, about, long_about = None)] pub struct DiscoverArgs { @@ -21,6 +22,7 @@ pub struct DiscoverArgs { pub extra: Vec, } +/// Arguments for ` discover` command #[derive(clap::Args, Debug)] #[command(version, about, long_about = None)] pub struct RunFileTestArgs { @@ -34,6 +36,7 @@ pub struct RunFileTestArgs { pub extra: Vec, } +/// Arguments for ` discover` command #[derive(clap::Args, Debug)] #[command(version, about, long_about = None)] pub struct DetectWorkspaceArgs { @@ -74,8 +77,10 @@ pub struct AdapterConfiguration { pub workspace_dir: Option, } +/// Result of ` detect-workspace` pub type DetectWorkspaceResult = HashMap>; +/// Result of ` run-file-test` #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct RunFileTestResultItem { pub path: String, @@ -98,4 +103,5 @@ pub struct DiscoverResultItem { pub tests: Vec, } +/// Result of ` discover` pub type DiscoverResult = Vec; From 6104ca0438c332d41198c747705bf336bdfccd16 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 16:48:34 +0900 Subject: [PATCH 042/139] refactor(client): fix typo --- crates/adapter/src/main.rs | 2 +- crates/adapter/src/model.rs | 16 ++++++++-------- crates/adapter/src/runner/cargo_nextest.rs | 2 +- crates/adapter/src/runner/cargo_test.rs | 2 +- crates/adapter/src/runner/deno.rs | 2 +- crates/adapter/src/runner/go.rs | 2 +- crates/adapter/src/runner/jest.rs | 2 +- crates/adapter/src/runner/vitest.rs | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/adapter/src/main.rs b/crates/adapter/src/main.rs index 9a70a9e..d98d13d 100644 --- a/crates/adapter/src/main.rs +++ b/crates/adapter/src/main.rs @@ -33,7 +33,7 @@ fn handle(commands: AdapterCommands) -> Result<(), LSError> { match commands { AdapterCommands::Discover(mut commands) => { let (extra, test_kind) = pick_test_from_extra(&mut commands.extra).unwrap(); - test_kind.disover(DiscoverArgs { extra, ..commands })?; + test_kind.discover(DiscoverArgs { extra, ..commands })?; Ok(()) } AdapterCommands::RunFileTest(mut commands) => { diff --git a/crates/adapter/src/model.rs b/crates/adapter/src/model.rs index 9a436cc..e22661f 100644 --- a/crates/adapter/src/model.rs +++ b/crates/adapter/src/model.rs @@ -21,14 +21,14 @@ pub enum AvailableTestKind { GoTest(GoTestRunner), } impl Runner for AvailableTestKind { - fn disover(&self, args: DiscoverArgs) -> Result<(), LSError> { + fn discover(&self, args: DiscoverArgs) -> Result<(), LSError> { match self { - AvailableTestKind::CargoTest(runner) => runner.disover(args), - AvailableTestKind::CargoNextest(runner) => runner.disover(args), - AvailableTestKind::Jest(runner) => runner.disover(args), - AvailableTestKind::Deno(runner) => runner.disover(args), - AvailableTestKind::GoTest(runner) => runner.disover(args), - AvailableTestKind::Vitest(runner) => runner.disover(args), + AvailableTestKind::CargoTest(runner) => runner.discover(args), + AvailableTestKind::CargoNextest(runner) => runner.discover(args), + AvailableTestKind::Jest(runner) => runner.discover(args), + AvailableTestKind::Deno(runner) => runner.discover(args), + AvailableTestKind::GoTest(runner) => runner.discover(args), + AvailableTestKind::Vitest(runner) => runner.discover(args), } } @@ -72,7 +72,7 @@ impl FromStr for AvailableTestKind { } pub trait Runner { - fn disover(&self, args: DiscoverArgs) -> Result<(), LSError>; + fn discover(&self, args: DiscoverArgs) -> Result<(), LSError>; fn run_file_test(&self, args: RunFileTestArgs) -> Result<(), LSError>; fn detect_workspaces(&self, args: DetectWorkspaceArgs) -> Result<(), LSError>; } diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index 7689d68..dc0c6da 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -31,7 +31,7 @@ fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { pub struct CargoNextestRunner; impl Runner for CargoNextestRunner { - fn disover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index bf98fe3..5a00055 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -31,7 +31,7 @@ fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { pub struct CargoTestRunner; impl Runner for CargoTestRunner { - fn disover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index 812cd99..9e2c20c 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -157,7 +157,7 @@ fn discover(file_path: &str) -> Result, LSError> { pub struct DenoRunner; impl Runner for DenoRunner { - fn disover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; for file_path in file_paths { diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 3d9e822..0e9b4ed 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -225,7 +225,7 @@ fn discover(file_path: &str) -> Result, LSError> { #[derive(Eq, PartialEq, Hash, Debug)] pub struct GoTestRunner; impl Runner for GoTestRunner { - fn disover( + fn discover( &self, args: testing_language_server::spec::DiscoverArgs, ) -> Result<(), testing_language_server::error::LSError> { diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index a926d24..59b0a5f 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -156,7 +156,7 @@ fn discover(file_path: &str) -> Result, LSError> { pub struct JestRunner; impl Runner for JestRunner { - fn disover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; for file_path in file_paths { diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 1cb38ee..3047c47 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -132,7 +132,7 @@ fn parse_diagnostics( } impl Runner for VitestRunner { - fn disover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; From 2ba8d3d22551169f63682574cd71d083e53cb863 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 17:13:39 +0900 Subject: [PATCH 043/139] fix: use valid field in payload --- src/main.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 45aed38..6375ce5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -99,13 +99,15 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { } } "$/runFileTest" => { - let uri = extract_uri(¶ms["uri"])?; + let uri = extract_uri(¶ms)?; server.check_file(&uri, false)?; } "$/discoverFileTest" => { let id = value["id"].as_i64().unwrap(); - let uri = extract_uri(¶ms["uri"])?; + let uri = extract_uri(¶ms)?; + tracing::info!("DEBUGPRINT[2]: main.rs:107: uri={:#?}", uri); let result = server.discover_file(&uri)?; + tracing::info!("DEBUGPRINT[1]: main.rs:108: result={:#?}", result); send_stdout(&json!({ "jsonrpc": "2.0", "id": id, From a8c52dc6c46f339369868640814e96959af69177 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 21:44:04 +0900 Subject: [PATCH 044/139] refactor: rename a variable --- src/main.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6375ce5..1c61221 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,14 +48,14 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { break 'read_header; } - let splitted: Vec<&str> = buffer.split(' ').collect(); + let split: Vec<&str> = buffer.split(' ').collect(); - if splitted.len() != 2 { + if split.len() != 2 { tracing::warn!("unexpected"); } - let header_name = splitted[0].to_lowercase(); - let header_value = splitted[1].trim(); + let header_name = split[0].to_lowercase(); + let header_value = split[1].trim(); match header_name.as_ref() { "content-length" => {} @@ -105,9 +105,7 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { "$/discoverFileTest" => { let id = value["id"].as_i64().unwrap(); let uri = extract_uri(¶ms)?; - tracing::info!("DEBUGPRINT[2]: main.rs:107: uri={:#?}", uri); let result = server.discover_file(&uri)?; - tracing::info!("DEBUGPRINT[1]: main.rs:108: result={:#?}", result); send_stdout(&json!({ "jsonrpc": "2.0", "id": id, From 48e397efd336d53be254f5c1b71246a9ec02434a Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 21:44:53 +0900 Subject: [PATCH 045/139] fix(adapter): prevent test name duplication --- crates/adapter/src/runner/util.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index 08b3c0d..54b60ef 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -140,6 +140,7 @@ pub fn discover_with_treesitter( let source = source_code.as_bytes(); let matches = cursor.matches(&query, tree.root_node(), source); let mut namespace = ""; + let mut test_id_set = HashSet::new(); for m in matches { let mut test_start_position = Point::default(); let mut test_end_position = Point::default(); @@ -162,6 +163,11 @@ pub fn discover_with_treesitter( } else { [namespace, value].join("::") }; + if test_id_set.contains(&test_id) { + continue; + } else { + test_id_set.insert(test_id.clone()); + } let test_item = TestItem { id: test_id.clone(), name: test_id, From ef51778b60b0b5f4191f1e9c338249abdccb0735 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 21:47:55 +0900 Subject: [PATCH 046/139] test(adapter): prevent test failure --- crates/adapter/src/runner/deno.rs | 4 ++-- demo/deno/main_test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index 9e2c20c..482d4ae 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -301,8 +301,8 @@ mod tests { } }, TestItem { - id: String::from("fail1"), - name: String::from("fail1"), + id: String::from("fail2"), + name: String::from("fail2"), start_position: Range { start: Position { line: 15, diff --git a/demo/deno/main_test.ts b/demo/deno/main_test.ts index 4604e1f..18556f6 100644 --- a/demo/deno/main_test.ts +++ b/demo/deno/main_test.ts @@ -13,6 +13,6 @@ Deno.test(function fail1() { assertEquals(add(2, 5), 5); }); -Deno.test(function fail1() { +Deno.test(function fail2() { assert(throwFn()); }); From c856f69086079e94210094f93cd35f717666cba2 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 21:54:40 +0900 Subject: [PATCH 047/139] refactor: fix comment --- src/spec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spec.rs b/src/spec.rs index e751759..d159e4a 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -22,7 +22,7 @@ pub struct DiscoverArgs { pub extra: Vec, } -/// Arguments for ` discover` command +/// Arguments for ` run-file-test` command #[derive(clap::Args, Debug)] #[command(version, about, long_about = None)] pub struct RunFileTestArgs { @@ -36,7 +36,7 @@ pub struct RunFileTestArgs { pub extra: Vec, } -/// Arguments for ` discover` command +/// Arguments for ` detect-workspace` command #[derive(clap::Args, Debug)] #[command(version, about, long_about = None)] pub struct DetectWorkspaceArgs { From a983a09a8e45029be481e4ad4e85ade49cef262c Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 22:08:40 +0900 Subject: [PATCH 048/139] feat: update adapter specification to distinguish between successful and failed tests in extensions --- src/spec.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/spec.rs b/src/spec.rs index d159e4a..c146888 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -85,6 +85,8 @@ pub type DetectWorkspaceResult = HashMap>; pub struct RunFileTestResultItem { pub path: String, pub diagnostics: Vec, + pub performed_test_ids: Vec, + pub failed_test_ids: Vec, } pub type RunFileTestResult = Vec; From 7a6d6e28b5f3182abb2515f0ea57980e8214bf89 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 13 Aug 2024 22:14:21 +0900 Subject: [PATCH 049/139] chore: update version --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1629da4..8ac08c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -605,6 +605,8 @@ dependencies = [ [[package]] name = "testing-language-server" version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad25ceae0685a3744fb8ac2b1e096cab4b9c30649344051d4c238e546871291" dependencies = [ "anyhow", "clap", @@ -625,9 +627,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad25ceae0685a3744fb8ac2b1e096cab4b9c30649344051d4c238e546871291" +version = "0.0.7" dependencies = [ "anyhow", "clap", @@ -658,7 +658,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "testing-language-server 0.0.6", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 7eb0097..c501b2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.6" +version = "0.0.7" edition = "2021" description = "LSP server for testing" license = "MIT" From 3131833238cb024054fc7bcafb83b2649650d475 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 14 Aug 2024 23:34:25 +0900 Subject: [PATCH 050/139] fix: revert specification due to design flaw --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/spec.rs | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ac08c2..1e1a213 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -627,7 +627,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.7" +version = "0.0.8" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index c501b2a..5f2566d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.7" +version = "0.0.8" edition = "2021" description = "LSP server for testing" license = "MIT" diff --git a/src/spec.rs b/src/spec.rs index c146888..d159e4a 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -85,8 +85,6 @@ pub type DetectWorkspaceResult = HashMap>; pub struct RunFileTestResultItem { pub path: String, pub diagnostics: Vec, - pub performed_test_ids: Vec, - pub failed_test_ids: Vec, } pub type RunFileTestResult = Vec; From 63e1c653d905d65fa10703eb048207b24e1ea2e4 Mon Sep 17 00:00:00 2001 From: kbwo Date: Thu, 15 Aug 2024 22:57:39 +0900 Subject: [PATCH 051/139] feat(adapter): write test result to file --- crates/adapter/src/runner/cargo_nextest.rs | 2 ++ crates/adapter/src/runner/cargo_test.rs | 2 ++ crates/adapter/src/runner/deno.rs | 2 ++ crates/adapter/src/runner/go.rs | 2 ++ crates/adapter/src/runner/jest.rs | 10 ++++------ crates/adapter/src/runner/util.rs | 13 +++++++++++++ crates/adapter/src/runner/vitest.rs | 18 ++++++------------ 7 files changed, 31 insertions(+), 18 deletions(-) diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index dc0c6da..ab3697b 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -14,6 +14,7 @@ use crate::model::Runner; use super::util::detect_workspaces_from_file_paths; use super::util::discover_rust_tests; use super::util::parse_cargo_diagnostics; +use super::util::write_result_log; fn parse_diagnostics( contents: &str, @@ -87,6 +88,7 @@ impl Runner for CargoNextestRunner { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stderr)?; + write_result_log("cargo_nextest.log", &test_result)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace_root).unwrap(), diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 5a00055..2f93936 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -14,6 +14,7 @@ use crate::model::Runner; use super::util::detect_workspaces_from_file_paths; use super::util::discover_rust_tests; use super::util::parse_cargo_diagnostics; +use super::util::write_result_log; fn parse_diagnostics( contents: &str, @@ -78,6 +79,7 @@ impl Runner for CargoTestRunner { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stdout)?; + write_result_log("cargo_test.log", &test_result)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace_root).unwrap(), diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index 482d4ae..6118b7a 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -23,6 +23,7 @@ use crate::model::Runner; use super::util::clean_ansi; use super::util::detect_workspaces_from_file_paths; use super::util::discover_with_treesitter; +use super::util::write_result_log; use super::util::MAX_CHAR_LENGTH; fn get_position_from_output(line: &str) -> Option<(String, u32, u32)> { @@ -187,6 +188,7 @@ impl Runner for DenoRunner { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stdout)?; + write_result_log("deno.log", &test_result)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace).unwrap(), diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 0e9b4ed..07e306d 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -20,6 +20,7 @@ use testing_language_server::spec::TestItem; use super::util::detect_workspaces_from_file_paths; use super::util::discover_with_treesitter; +use super::util::write_result_log; use super::util::MAX_CHAR_LENGTH; #[derive(Deserialize, Eq, PartialEq)] @@ -262,6 +263,7 @@ impl Runner for GoTestRunner { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stdout)?; + write_result_log("go.log", &test_result)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace).unwrap(), diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 59b0a5f..b9e8125 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -4,7 +4,6 @@ use lsp_types::DiagnosticSeverity; use serde_json::Value; use std::collections::HashMap; use std::fs; -use tempfile::tempdir; use testing_language_server::error::LSError; use testing_language_server::spec::DetectWorkspaceResult; @@ -19,6 +18,7 @@ use crate::model::Runner; use super::util::clean_ansi; use super::util::detect_workspaces_from_file_paths; use super::util::discover_with_treesitter; +use super::util::LOG_LOCATION; use super::util::MAX_CHAR_LENGTH; fn parse_diagnostics( @@ -175,9 +175,7 @@ impl Runner for JestRunner { ) -> Result<(), LSError> { let file_paths = args.file_paths; let workspace_root = args.workspace; - let tempdir = tempdir().unwrap(); - let tempdir_path = tempdir.path(); - let tempfile_path = tempdir_path.join("jest.json"); + let log_path = LOG_LOCATION.join("jest.json"); std::process::Command::new("jest") .current_dir(&workspace_root) .args([ @@ -187,11 +185,11 @@ impl Runner for JestRunner { "--verbose", "--json", "--outputFile", - tempfile_path.to_str().unwrap(), + log_path.to_str().unwrap(), ]) .output() .unwrap(); - let test_result = fs::read_to_string(tempfile_path)?; + let test_result = fs::read_to_string(log_path)?; let diagnostics: RunFileTestResult = parse_diagnostics(&test_result, file_paths)?; send_stdout(&diagnostics)?; Ok(()) diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index 54b60ef..fc95a5d 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -1,6 +1,8 @@ use std::collections::{HashMap, HashSet}; +use std::io; use std::path::{Path, PathBuf}; use std::str::FromStr; +use std::sync::LazyLock; use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; use regex::Regex; @@ -9,6 +11,11 @@ use testing_language_server::spec::{RunFileTestResultItem, TestItem}; use testing_language_server::{error::LSError, spec::RunFileTestResult}; use tree_sitter::{Language, Point, Query, QueryCursor}; +pub static LOG_LOCATION: LazyLock = LazyLock::new(|| { + let home_dir = dirs::home_dir().unwrap(); + home_dir.join(".config/testing_language_server/adapter/") +}); + // If the character value is greater than the line length it defaults back to the line length. pub const MAX_CHAR_LENGTH: u32 = 10000; @@ -284,3 +291,9 @@ pub fn resolve_path(base_dir: &Path, relative_path: &str) -> PathBuf { PathBuf::from_iter(components) } + +pub fn write_result_log(file_name: &str, content: &str) -> io::Result<()> { + let log_path = LOG_LOCATION.join(file_name); + std::fs::write(&log_path, content)?; + Ok(()) +} diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 3047c47..b8226f7 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -1,11 +1,10 @@ use std::{ collections::HashMap, - fs::{self, File}, + fs::{self}, }; use lsp_types::{Diagnostic, DiagnosticSeverity}; use serde_json::Value; -use tempfile::tempdir; use testing_language_server::{ error::LSError, spec::{ @@ -17,7 +16,7 @@ use crate::model::Runner; use super::util::{ clean_ansi, detect_workspaces_from_file_paths, discover_with_treesitter, send_stdout, - MAX_CHAR_LENGTH, + LOG_LOCATION, MAX_CHAR_LENGTH, }; #[derive(Eq, PartialEq, Hash, Debug)] @@ -153,26 +152,21 @@ impl Runner for VitestRunner { ) -> Result<(), LSError> { let file_paths = args.file_paths; let workspace_root = args.workspace; - let tempdir = tempdir().unwrap(); - let tempdir_path = tempdir.path(); - let tempfile_path = tempdir_path.join("vitest.json"); - let tempfile = File::create(&tempfile_path)?; - let tempfile_path = tempfile_path.to_str().unwrap(); + let log_path = LOG_LOCATION.join("vitest.json"); + let log_path = log_path.to_str().unwrap(); std::process::Command::new("vitest") .current_dir(&workspace_root) .args([ "--watch=false", "--reporter=json", "--outputFile=", - tempfile_path, + log_path, ]) .output() .unwrap(); - let test_result = fs::read_to_string(tempfile_path)?; + let test_result = fs::read_to_string(log_path)?; let diagnostics: RunFileTestResult = parse_diagnostics(&test_result, file_paths)?; send_stdout(&diagnostics)?; - drop(tempfile); - let _ = tempdir.close(); Ok(()) } From cce066cd2abbe9364fe3e4b84386e6410ce86592 Mon Sep 17 00:00:00 2001 From: kbwo Date: Thu, 15 Aug 2024 23:14:06 +0900 Subject: [PATCH 052/139] feat: add method to run workspace test --- src/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1c61221..5dc3a52 100644 --- a/src/main.rs +++ b/src/main.rs @@ -99,12 +99,15 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { } } "$/runFileTest" => { - let uri = extract_uri(¶ms)?; + let uri = extract_uri(params)?; server.check_file(&uri, false)?; } + "$/runWorkspaceTest" => { + server.diagnose_workspace()?; + } "$/discoverFileTest" => { let id = value["id"].as_i64().unwrap(); - let uri = extract_uri(¶ms)?; + let uri = extract_uri(params)?; let result = server.discover_file(&uri)?; send_stdout(&json!({ "jsonrpc": "2.0", From b08c350b7828045fbc96f01ec775004d2d49e691 Mon Sep 17 00:00:00 2001 From: kbwo Date: Thu, 15 Aug 2024 23:14:45 +0900 Subject: [PATCH 053/139] chore: update version --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/adapter/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e1a213..b9c3938 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -627,7 +627,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.8" +version = "0.0.9" dependencies = [ "anyhow", "clap", @@ -648,7 +648,7 @@ dependencies = [ [[package]] name = "testing-ls-adapter" -version = "0.0.3" +version = "0.0.5" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index 5f2566d..23802ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.8" +version = "0.0.9" edition = "2021" description = "LSP server for testing" license = "MIT" diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 9093de0..184535a 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.3" +version = "0.0.5" edition = "2021" description = "testing-language-server adapter" license = "MIT" From daa8db434c6730501bf5b9eec3387e982f0ad0be Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 17 Aug 2024 16:27:58 +0900 Subject: [PATCH 054/139] chore(adapter): write both of stdout and stderr to log --- crates/adapter/src/runner/cargo_nextest.rs | 6 +++--- crates/adapter/src/runner/cargo_test.rs | 5 +++-- crates/adapter/src/runner/deno.rs | 2 +- crates/adapter/src/runner/go.rs | 6 +++--- crates/adapter/src/runner/util.rs | 6 +++++- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index ab3697b..2913155 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -77,18 +77,18 @@ impl Runner for CargoNextestRunner { .args(tests) .output() .unwrap(); + let output = test_result; + write_result_log("cargo_nextest.log", &output)?; let Output { stdout, stderr, status, - .. - } = test_result; + } = output; let unexpected_status_code = status.code().map(|code| code != 100); if stdout.is_empty() && !stderr.is_empty() && unexpected_status_code.unwrap_or(false) { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stderr)?; - write_result_log("cargo_nextest.log", &test_result)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace_root).unwrap(), diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 2f93936..bfd02d9 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -74,12 +74,13 @@ impl Runner for CargoTestRunner { .args(tests) .output() .unwrap(); - let Output { stdout, stderr, .. } = test_result; + let output = test_result; + write_result_log("cargo_test.log", &output)?; + let Output { stdout, stderr, .. } = output; if stdout.is_empty() && !stderr.is_empty() { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stdout)?; - write_result_log("cargo_test.log", &test_result)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace_root).unwrap(), diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index 6118b7a..9db0735 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -183,12 +183,12 @@ impl Runner for DenoRunner { .args(&file_paths) .output() .unwrap(); + write_result_log("deno.log", &output)?; let Output { stdout, stderr, .. } = output; if stdout.is_empty() { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stdout)?; - write_result_log("deno.log", &test_result)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace).unwrap(), diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 07e306d..86638e4 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -251,19 +251,19 @@ impl Runner for GoTestRunner { let file_paths = args.file_paths; let default_args = ["-v", "-json", "", "-count=1", "-timeout=60s"]; let workspace = args.workspace; - let test_result = std::process::Command::new("go") + let output = std::process::Command::new("go") .current_dir(&workspace) .arg("test") .args(default_args) .args(args.extra) .output() .unwrap(); - let Output { stdout, stderr, .. } = test_result; + write_result_log("go.log", &output)?; + let Output { stdout, stderr, .. } = output; if stdout.is_empty() && !stderr.is_empty() { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stdout)?; - write_result_log("go.log", &test_result)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace).unwrap(), diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index fc95a5d..deeee1d 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -1,6 +1,7 @@ use std::collections::{HashMap, HashSet}; use std::io; use std::path::{Path, PathBuf}; +use std::process::Output; use std::str::FromStr; use std::sync::LazyLock; @@ -292,7 +293,10 @@ pub fn resolve_path(base_dir: &Path, relative_path: &str) -> PathBuf { PathBuf::from_iter(components) } -pub fn write_result_log(file_name: &str, content: &str) -> io::Result<()> { +pub fn write_result_log(file_name: &str, output: &Output) -> io::Result<()> { + let stdout = String::from_utf8(output.stdout.clone()).unwrap(); + let stderr = String::from_utf8(output.stderr.clone()).unwrap(); + let content = format!("stdout:\n{}\nstderr:\n{}", stdout, stderr); let log_path = LOG_LOCATION.join(file_name); std::fs::write(&log_path, content)?; Ok(()) From 73a179f90bd8cd2de23a39cf019b668200ecafbd Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 23 Sep 2024 11:18:15 +0900 Subject: [PATCH 055/139] feat: handle `shutdown` and `exit` close #33 --- src/main.rs | 7 +++++++ src/server.rs | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main.rs b/src/main.rs index 5dc3a52..260a9c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -85,6 +85,13 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { let id = value["id"].as_i64().unwrap(); server.initialize(id, initialize_params)?; } + "shutdown" => { + let id = value["id"].as_i64().unwrap(); + server.shutdown(id)?; + } + "exit" => { + std::process::exit(0); + } "workspace/diagnostic" => { server.diagnose_workspace()?; } diff --git a/src/server.rs b/src/server.rs index 8d4dfc9..7fbbe36 100644 --- a/src/server.rs +++ b/src/server.rs @@ -452,6 +452,15 @@ impl TestingLS { }))?; Ok(()) } + + pub fn shutdown(&self, id: i64) -> Result<(), LSError> { + send_stdout(&json!({ + "jsonrpc": "2.0", + "id": id, + "method": json!(null), + }))?; + Ok(()) + } } #[cfg(test)] From 3e3d4c5db1c0307d907aaff4947a7bd15286260d Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 24 Aug 2024 22:54:18 +0900 Subject: [PATCH 056/139] feat: implement phpunit adapter --- CONTRIBUTING.md | 9 + Cargo.lock | 19 + Cargo.toml | 1 + crates/adapter/Cargo.toml | 2 + crates/adapter/src/model.rs | 6 + crates/adapter/src/runner/mod.rs | 1 + crates/adapter/src/runner/phpunit.rs | 338 ++++++ demo/.vim/coc-settings.json | 26 +- demo/phpunit/.gitignore | 1 + demo/phpunit/.mise.toml | 2 + demo/phpunit/composer.json | 17 + demo/phpunit/composer.lock | 1651 ++++++++++++++++++++++++++ demo/phpunit/output.xml | 15 + demo/phpunit/src/Calculator.php | 16 + demo/phpunit/src/CalculatorTest.php | 30 + 15 files changed, 2125 insertions(+), 9 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 crates/adapter/src/runner/phpunit.rs create mode 100644 demo/phpunit/.gitignore create mode 100644 demo/phpunit/.mise.toml create mode 100644 demo/phpunit/composer.json create mode 100644 demo/phpunit/composer.lock create mode 100644 demo/phpunit/output.xml create mode 100644 demo/phpunit/src/Calculator.php create mode 100644 demo/phpunit/src/CalculatorTest.php diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8748667 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,9 @@ +# Getting started + +```sh +cargo install just +cargo install cargo-watch +just watch-build +sudo ln -s $(pwd)/target/debug/testing-language-server /usr/local/bin/testing-language-server +sudo ln -s $(pwd)/target/debug/testing-ls-adapter /usr/local/bin/testing-ls-adapter +``` diff --git a/Cargo.lock b/Cargo.lock index b9c3938..acd5144 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -644,6 +644,7 @@ dependencies = [ "tracing", "tracing-appender", "tracing-subscriber", + "tree-sitter-php", ] [[package]] @@ -665,7 +666,9 @@ dependencies = [ "tree-sitter", "tree-sitter-go", "tree-sitter-javascript", + "tree-sitter-php", "tree-sitter-rust", + "xml-rs", ] [[package]] @@ -828,6 +831,16 @@ dependencies = [ "tree-sitter", ] +[[package]] +name = "tree-sitter-php" +version = "0.22.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be890bd043986cc26b69968698e508dbd40060805e482f226dc873a63a88d60" +dependencies = [ + "cc", + "tree-sitter", +] + [[package]] name = "tree-sitter-rust" version = "0.21.2" @@ -1040,3 +1053,9 @@ name = "windows_x86_64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "xml-rs" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601" diff --git a/Cargo.toml b/Cargo.toml index 23802ea..0186f45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,3 +46,4 @@ once_cell = { workspace = true } strum = { workspace = true, features = ["derive"] } glob = { workspace = true } globwalk = "0.9.1" +tree-sitter-php = "0.22.8" diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 184535a..b1abe8a 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -20,7 +20,9 @@ anyhow = { workspace = true } tempfile = "3.10.1" tree-sitter-javascript = "0.21.0" tree-sitter-go = "0.21.0" +tree-sitter-php = "0.22.5" tracing-appender = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true, default-features = false } dirs = "5.0.1" +xml-rs = "0.8.21" diff --git a/crates/adapter/src/model.rs b/crates/adapter/src/model.rs index e22661f..44d987e 100644 --- a/crates/adapter/src/model.rs +++ b/crates/adapter/src/model.rs @@ -2,6 +2,7 @@ use crate::runner::cargo_nextest::CargoNextestRunner; use crate::runner::cargo_test::CargoTestRunner; use crate::runner::deno::DenoRunner; use crate::runner::go::GoTestRunner; +use crate::runner::phpunit::PhpunitRunner; use crate::runner::vitest::VitestRunner; use std::str::FromStr; use testing_language_server::error::LSError; @@ -19,6 +20,7 @@ pub enum AvailableTestKind { Vitest(VitestRunner), Deno(DenoRunner), GoTest(GoTestRunner), + Phpunit(PhpunitRunner), } impl Runner for AvailableTestKind { fn discover(&self, args: DiscoverArgs) -> Result<(), LSError> { @@ -29,6 +31,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::Deno(runner) => runner.discover(args), AvailableTestKind::GoTest(runner) => runner.discover(args), AvailableTestKind::Vitest(runner) => runner.discover(args), + AvailableTestKind::Phpunit(runner) => runner.discover(args), } } @@ -40,6 +43,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::Deno(runner) => runner.run_file_test(args), AvailableTestKind::GoTest(runner) => runner.run_file_test(args), AvailableTestKind::Vitest(runner) => runner.run_file_test(args), + AvailableTestKind::Phpunit(runner) => runner.run_file_test(args), } } @@ -51,6 +55,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::Deno(runner) => runner.detect_workspaces(args), AvailableTestKind::GoTest(runner) => runner.detect_workspaces(args), AvailableTestKind::Vitest(runner) => runner.detect_workspaces(args), + AvailableTestKind::Phpunit(runner) => runner.detect_workspaces(args), } } } @@ -66,6 +71,7 @@ impl FromStr for AvailableTestKind { "go-test" => Ok(AvailableTestKind::GoTest(GoTestRunner)), "vitest" => Ok(AvailableTestKind::Vitest(VitestRunner)), "deno" => Ok(AvailableTestKind::Deno(DenoRunner)), + "phpunit" => Ok(AvailableTestKind::Phpunit(PhpunitRunner)), _ => Err(anyhow::anyhow!("Unknown test kind: {}", s)), } } diff --git a/crates/adapter/src/runner/mod.rs b/crates/adapter/src/runner/mod.rs index ba750e2..996bd5e 100644 --- a/crates/adapter/src/runner/mod.rs +++ b/crates/adapter/src/runner/mod.rs @@ -3,5 +3,6 @@ pub mod cargo_test; pub mod deno; pub mod go; pub mod jest; +pub mod phpunit; pub mod util; pub mod vitest; diff --git a/crates/adapter/src/runner/phpunit.rs b/crates/adapter/src/runner/phpunit.rs new file mode 100644 index 0000000..18f3c26 --- /dev/null +++ b/crates/adapter/src/runner/phpunit.rs @@ -0,0 +1,338 @@ +use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; +use std::fs::File; +use std::io::BufReader; +use std::process::Output; +use testing_language_server::error::LSError; +use testing_language_server::spec::{ + DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, RunFileTestResult, + RunFileTestResultItem, TestItem, +}; +use xml::reader::{ParserConfig, XmlEvent}; + +use crate::model::Runner; + +use super::util::{ + detect_workspaces_from_file_paths, discover_with_treesitter, send_stdout, LOG_LOCATION, + MAX_CHAR_LENGTH, +}; + +#[derive(Debug)] +pub struct ResultFromXml { + pub message: String, + pub path: String, + pub line: u32, +} + +impl Into for ResultFromXml { + fn into(self) -> RunFileTestResultItem { + RunFileTestResultItem { + path: self.path, + diagnostics: vec![Diagnostic { + message: self.message, + range: Range { + start: Position { + line: self.line - 1, + character: 0, + }, + end: Position { + line: self.line - 1, + character: MAX_CHAR_LENGTH, + }, + }, + severity: Some(DiagnosticSeverity::ERROR), + ..Default::default() + }], + } + } +} + +fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { + detect_workspaces_from_file_paths(&file_paths, &["composer.json".to_string()]) +} + +fn get_result_from_characters(characters: &str) -> Result { + // characters can be like + // Tests\\CalculatorTest::testFail1\nFailed asserting that 8 matches expected 1.\n\n/home/kbwo/projects/github.com/kbwo/testing-language-server/demo/phpunit/src/CalculatorTest.php:28 + let mut split = characters.split("\n\n"); + let message = split + .next() + .unwrap() + .trim_start_matches("Failed asserting that ") + .trim_end_matches(".") + .to_string(); + let location = split.next().unwrap().to_string(); + let mut split_location = location.split(":"); + + let path = split_location.next().unwrap().to_string(); + let line = split_location.next().unwrap().parse().unwrap(); + Ok(ResultFromXml { + message, + path, + line, + }) +} + +fn get_result_from_xml(path: &str) -> Result, anyhow::Error> { + use xml::common::Position; + + let file = File::open(path).unwrap(); + let mut reader = ParserConfig::default() + .ignore_root_level_whitespace(false) + .create_reader(BufReader::new(file)); + + let local_name = "failure"; + + let mut in_failure = false; + let mut result: Vec = Vec::new(); + loop { + match reader.next() { + Ok(e) => match e { + XmlEvent::StartElement { name, .. } => { + if name.local_name.starts_with(local_name) { + in_failure = true; + } + } + XmlEvent::EndElement { .. } => { + in_failure = false; + } + XmlEvent::Characters(data) => { + if let Ok(result_from_xml) = get_result_from_characters(&data) { + if in_failure { + result.push(result_from_xml); + } + } + } + XmlEvent::EndDocument => break, + _ => {} + }, + Err(e) => { + tracing::error!("Error at {}: {e}", reader.position()); + break; + } + } + } + + Ok(result) +} + +fn discover(file_path: &str) -> Result, LSError> { + // from https://github.com/olimorris/neotest-phpunit/blob/bbd79d95e927ccd16f0e1d765060058d34838e2e/lua/neotest-phpunit/init.lua#L111 + // license: https://github.com/olimorris/neotest-phpunit/blob/bbd79d95e927ccd16f0e1d765060058d34838e2e/LICENSE + let query = r#" + ((class_declaration + name: (name) @namespace.name (#match? @namespace.name "Test") + )) @namespace.definition + + ((method_declaration + (attribute_list + (attribute_group + (attribute) @test_attribute (#match? @test_attribute "Test") + ) + ) + ( + (visibility_modifier) + (name) @test.name + ) @test.definition + )) + + ((method_declaration + (name) @test.name (#match? @test.name "test") + )) @test.definition + + (((comment) @test_comment (#match? @test_comment "\\@test") . + (method_declaration + (name) @test.name + ) @test.definition + )) + "#; + discover_with_treesitter(file_path, &tree_sitter_php::language_php(), query) +} + +#[derive(Eq, PartialEq, Debug)] +pub struct PhpunitRunner; + +impl Runner for PhpunitRunner { + fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + let file_paths = args.file_paths; + let mut discover_results: DiscoverResult = vec![]; + for file_path in file_paths { + discover_results.push(DiscoverResultItem { + tests: discover(&file_path)?, + path: file_path, + }) + } + send_stdout(&discover_results)?; + Ok(()) + } + + fn run_file_test( + &self, + args: testing_language_server::spec::RunFileTestArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let workspace_root = args.workspace; + let log_path = LOG_LOCATION.join("phpunit.xml"); + let tests = file_paths + .iter() + .map(|path| { + discover(path).map(|test_items| { + test_items + .into_iter() + .map(|item| item.id) + .collect::>() + }) + }) + .filter_map(Result::ok) + .flatten() + .collect::>(); + let test_names = tests.join("|"); + let filter_pattern = format!("/{test_names}/"); + let output = std::process::Command::new("phpunit") + .current_dir(&workspace_root) + .args([ + "--log-junit", + log_path.to_str().unwrap(), + "--filter", + &filter_pattern, + ]) + .args(file_paths) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .output() + .unwrap(); + let Output { stdout, stderr, .. } = output; + if stdout.is_empty() && !stderr.is_empty() { + return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); + } + let result_from_xml = get_result_from_xml(log_path.to_str().unwrap())?; + let diagnostics: RunFileTestResult = result_from_xml + .into_iter() + .map(|result_from_xml| { + let result_item: RunFileTestResultItem = result_from_xml.into(); + result_item + }) + .collect(); + send_stdout(&diagnostics)?; + Ok(()) + } + + fn detect_workspaces( + &self, + args: testing_language_server::spec::DetectWorkspaceArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let detect_result = detect_workspaces(file_paths); + send_stdout(&detect_result)?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use lsp_types::{Position, Range}; + + use crate::runner::util::MAX_CHAR_LENGTH; + + use super::*; + + #[test] + fn parse_xml() { + let mut path = std::env::current_dir().unwrap(); + path.push("../../demo/phpunit/output.xml"); + let result = get_result_from_xml(path.to_str().unwrap()).unwrap(); + assert_eq!(result.len(), 1); + assert_eq!( + result[0].message, + "Tests\\CalculatorTest::testFail1\nFailed asserting that 8 matches expected 1" + ); + assert_eq!( + result[0].path, + "/home/kbwo/testing-language-server/demo/phpunit/src/CalculatorTest.php" + ); + assert_eq!(result[0].line, 28); + } + + #[test] + fn test_discover() { + let file_path = "../../demo/phpunit/src/CalculatorTest.php"; + let test_items = discover(file_path).unwrap(); + assert_eq!(test_items.len(), 3); + assert_eq!( + test_items, + [ + TestItem { + id: "CalculatorTest::testAdd".to_string(), + name: "CalculatorTest::testAdd".to_string(), + start_position: Range { + start: Position { + line: 9, + character: 4 + }, + end: Position { + line: 9, + character: MAX_CHAR_LENGTH + } + }, + end_position: Range { + start: Position { + line: 14, + character: 0 + }, + end: Position { + line: 14, + character: 5 + } + } + }, + TestItem { + id: "CalculatorTest::testSubtract".to_string(), + name: "CalculatorTest::testSubtract".to_string(), + start_position: Range { + start: Position { + line: 16, + character: 4 + }, + end: Position { + line: 16, + character: MAX_CHAR_LENGTH + } + }, + end_position: Range { + start: Position { + line: 21, + character: 0 + }, + end: Position { + line: 21, + character: 5 + } + } + }, + TestItem { + id: "CalculatorTest::testFail1".to_string(), + name: "CalculatorTest::testFail1".to_string(), + start_position: Range { + start: Position { + line: 23, + character: 4 + }, + end: Position { + line: 23, + character: MAX_CHAR_LENGTH + } + }, + end_position: Range { + start: Position { + line: 28, + character: 0 + }, + end: Position { + line: 28, + character: 5 + } + } + } + ] + ) + } +} diff --git a/demo/.vim/coc-settings.json b/demo/.vim/coc-settings.json index c67a4dd..4a72552 100644 --- a/demo/.vim/coc-settings.json +++ b/demo/.vim/coc-settings.json @@ -3,17 +3,17 @@ "testing": { "command": "testing-language-server", "trace.server": "verbose", - "filetypes": ["rust", "javascript", "go", "typescript"], + "filetypes": ["rust", "javascript", "go", "typescript", "php"], "initializationOptions": { "adapterCommand": { - // "cargo-test": [ - // { - // "path": "testing-ls-adapter", - // "extra_args": ["--test-kind=cargo-test"], - // "include_patterns": ["/**/src/**/*.rs"], - // "exclude_patterns": ["/**/target/**"] - // } - // ], + "cargo-test": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=cargo-test"], + "include_patterns": ["/**/src/**/*.rs"], + "exclude_patterns": ["/**/target/**"] + } + ], "cargo-nextest": [ { "path": "testing-ls-adapter", @@ -56,6 +56,14 @@ "include_patterns": ["/**/*.go"], "exclude_patterns": [] } + ], + "phpunit": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=phpunit"], + "include_patterns": ["/**/*Test.php"], + "exclude_patterns": ["/phpunit/vendor/**/*.php"] + } ] } } diff --git a/demo/phpunit/.gitignore b/demo/phpunit/.gitignore new file mode 100644 index 0000000..22d0d82 --- /dev/null +++ b/demo/phpunit/.gitignore @@ -0,0 +1 @@ +vendor diff --git a/demo/phpunit/.mise.toml b/demo/phpunit/.mise.toml new file mode 100644 index 0000000..986fbc9 --- /dev/null +++ b/demo/phpunit/.mise.toml @@ -0,0 +1,2 @@ +[tools] +php = "8.3" diff --git a/demo/phpunit/composer.json b/demo/phpunit/composer.json new file mode 100644 index 0000000..38b0dea --- /dev/null +++ b/demo/phpunit/composer.json @@ -0,0 +1,17 @@ +{ + "name": "kbwo/phpunit", + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "authors": [ + { + "name": "kbwo", + "email": "kabaaa1126@gmail.com" + } + ], + "require-dev": { + "phpunit/phpunit": "^11.3" + } +} diff --git a/demo/phpunit/composer.lock b/demo/phpunit/composer.lock new file mode 100644 index 0000000..c8acf27 --- /dev/null +++ b/demo/phpunit/composer.lock @@ -0,0 +1,1651 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "c7577df748f63369fac3eda718711411", + "packages": [], + "packages-dev": [ + { + "name": "myclabs/deep-copy", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-06-12T14:39:25+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.1.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + }, + "time": "2024-07-01T20:03:41+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "19b6365ab8b59a64438c0c3f4241feeb480c9861" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/19b6365ab8b59a64438c0c3f4241feeb480c9861", + "reference": "19b6365ab8b59a64438c0c3f4241feeb480c9861", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.0", + "phpunit/php-text-template": "^4.0", + "sebastian/code-unit-reverse-lookup": "^4.0", + "sebastian/complexity": "^4.0", + "sebastian/environment": "^7.0", + "sebastian/lines-of-code": "^3.0", + "sebastian/version": "^5.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:05:37+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6ed896bf50bbbfe4d504a33ed5886278c78e4a26", + "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:06:37+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "fe179875ef0c14e90b75617002767eae0a742641" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fe179875ef0c14e90b75617002767eae0a742641", + "reference": "fe179875ef0c14e90b75617002767eae0a742641", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.5", + "phpunit/php-file-iterator": "^5.0.1", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.1", + "sebastian/comparator": "^6.0.2", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.1.3", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.0.1", + "sebastian/version": "^5.0.1" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.3-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.3.1" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-08-13T06:14:23+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:44:28+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/450d8f237bd611c45b5acf0733ce43e6bb280f81", + "reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-12T06:07:25+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:54:44+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:56:19+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:10:34+00:00" + }, + { + "name": "sebastian/type", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb6a6566f9589e86661291d13eba708cce5eb4aa", + "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:11:49+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/45c9debb7d039ce9b97de2f749c2cf5832a06ac4", + "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:13:08+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/demo/phpunit/output.xml b/demo/phpunit/output.xml new file mode 100644 index 0000000..6fbd193 --- /dev/null +++ b/demo/phpunit/output.xml @@ -0,0 +1,15 @@ + + + + + + + + Tests\CalculatorTest::testFail1 +Failed asserting that 8 matches expected 1. + +/home/kbwo/testing-language-server/demo/phpunit/src/CalculatorTest.php:28 + + + + diff --git a/demo/phpunit/src/Calculator.php b/demo/phpunit/src/Calculator.php new file mode 100644 index 0000000..797c1dd --- /dev/null +++ b/demo/phpunit/src/Calculator.php @@ -0,0 +1,16 @@ +add(2, 3); + $this->assertEquals(5, $result); + } + + public function testSubtract() + { + $calculator = new Calculator(); + $result = $calculator->subtract(5, 3); + $this->assertEquals(2, $result); + } + + public function testFail1() + { + $calculator = new Calculator(); + $result = $calculator->subtract(10, 2); + $this->assertEquals(1, $result); + } +} From 9bb28ea59218745571722f6da12ff09070ca7351 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 23 Sep 2024 17:54:42 +0900 Subject: [PATCH 057/139] chore: add log --- src/server.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/server.rs b/src/server.rs index 8d4dfc9..fe24f0f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -328,16 +328,21 @@ impl TestingLS { let adapter_result = String::from_utf8(stdout).map_err(|err| LSError::Adapter(err.to_string()))?; - if let Ok(res) = serde_json::from_str::(&adapter_result) { - for target_file in paths { - let diagnostics_for_file: Vec = res - .clone() - .into_iter() - .filter(|RunFileTestResultItem { path, .. }| path == target_file) - .flat_map(|RunFileTestResultItem { diagnostics, .. }| diagnostics) - .collect(); - let uri = Url::from_file_path(target_file.replace("file://", "")).unwrap(); - diagnostics.push((uri.to_string(), diagnostics_for_file)); + match serde_json::from_str::(&adapter_result) { + Ok(res) => { + for target_file in paths { + let diagnostics_for_file: Vec = res + .clone() + .into_iter() + .filter(|RunFileTestResultItem { path, .. }| path == target_file) + .flat_map(|RunFileTestResultItem { diagnostics, .. }| diagnostics) + .collect(); + let uri = Url::from_file_path(target_file.replace("file://", "")).unwrap(); + diagnostics.push((uri.to_string(), diagnostics_for_file)); + } + } + Err(err) => { + tracing::error!("Failed to parse adapter result: {:?}", err); } } Ok(diagnostics) From 8f4097aab3739188c43ad7eecfc9f2413a0662b9 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 23 Sep 2024 17:55:04 +0900 Subject: [PATCH 058/139] chore: add vscode settings for debugging with vscode-tesitng-ls --- demo/.vscode/settings.json | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 demo/.vscode/settings.json diff --git a/demo/.vscode/settings.json b/demo/.vscode/settings.json new file mode 100644 index 0000000..442dcda --- /dev/null +++ b/demo/.vscode/settings.json @@ -0,0 +1,60 @@ +{ + "testing.enable": true, + "testing.fileTypes": ["rust"], + "testing.adapterCommand": { + "cargo-nextest": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=cargo-nextest"], + "include_patterns": ["/**/src/**/*.rs"], + "exclude_patterns": ["/**/target/**"] + } + ], + "jest": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=jest"], + "include_patterns": ["/jest/*.js"], + "exclude_patterns": ["/jest/**/node_modules/**/*"] + } + ], + "vitest": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=vitest"], + "include_patterns": [ + "/vitest/*.test.ts", + "/vitest/config/**/*.test.ts" + ], + "exclude_patterns": ["/vitest/**/node_modules/**/*"] + } + ], + "deno": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=deno"], + "include_patterns": ["/deno/*.ts"], + "exclude_patterns": [] + } + ], + "go": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=go-test"], + "include_patterns": ["/**/*.go"], + "exclude_patterns": [] + } + ], + "phpunit": [ + { + "path": "testing-ls-adapter", + "extra_args": ["--test-kind=phpunit"], + "include_patterns": ["/**/*Test.php"], + "exclude_patterns": ["/phpunit/vendor/**/*.php"] + } + ] + }, + "testing.enableWorkspaceDiagnostics": true, + "testing.server.path": "testing-language-server", + "testing.trace.server": "verbose" +} From 20ae3b348784f68c3b734610bdbe9d152c212b70 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 29 Sep 2024 00:53:43 +0900 Subject: [PATCH 059/139] docs: add documentation for adapter --- doc/ADAPTER_SPEC.md | 49 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 doc/ADAPTER_SPEC.md diff --git a/doc/ADAPTER_SPEC.md b/doc/ADAPTER_SPEC.md new file mode 100644 index 0000000..3b0a54d --- /dev/null +++ b/doc/ADAPTER_SPEC.md @@ -0,0 +1,49 @@ +# Adapter Specifications + +This document outlines the command specifications. + +# Commands + +These commands must be implemented by the adapter. + +- **discover**: Initiates the discovery process. +- **run-file-test**: Executes tests on specified files. +- **detect-workspace**: Identifies the workspace based on provided parameters. + +## discover + +### Arguments +- `file_paths`: A list of file paths to be processed. + +### Stdout +Returns a JSON array of discovered items. Each item is a JSON object containing: +- `path`: String representing the file path. +- `tests`: Array of test items, where each test item is a JSON object including: + - `id`: String identifier for the test. + - `name`: String name of the test. + - `start_position`: [Range](https://docs.rs/lsp-types/latest/lsp_types/struct.Range.html) indicating the start position of the test in the file. + - `end_position`: [Range](https://docs.rs/lsp-types/latest/lsp_types/struct.Range.html) indicating the end position of the test in the file. + +## run-file-test + +### Arguments +- `file_paths`: A list of file paths to be tested. +- `workspace`: The workspace identifier where the tests will be executed. + +### Stdout +Returns a JSON array of test results. Each result is a JSON object containing: +- `path`: String representing the file path. +- `diagnostics`: Array of [Diagnostic](https://docs.rs/lsp-types/latest/lsp_types/struct.Diagnostic.html) objects. + +## detect-workspace + +### Arguments +- `file_paths`: A list of file paths to identify the workspace. + +### Stdout +Returns a JSON object where: +- Keys are strings representing workspace file paths. +- Values are arrays of strings representing file paths associated with each workspace. + +# Note: All stdout must be valid JSON and should be parseable by standard JSON parsers. + From ded6f382ac8612a9db24f787efa88df7fa0d611d Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 29 Sep 2024 00:54:01 +0900 Subject: [PATCH 060/139] docs: update README --- README.md | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 441041e..eb21e73 100644 --- a/README.md +++ b/README.md @@ -4,23 +4,31 @@ General purpose LSP server that integrate with testing. The language server is characterized by portability and extensibility. ## Motivation + This LSP server is heavily influenced by the following tools - [neotest](https://github.com/nvim-neotest/neotest) - [Wallaby.js](https://wallabyjs.com) These tools are very useful and powerful. However, they depend on the execution environment, such as VSCode and NeoVim, and the portability aspect was inconvenient for me. -So, I designed this testing-language-server and its dedicated adapters for each test tool to be the middle layer to the parts that depend on each editor. +So, I designed this testing-language-server and its dedicated adapters for each test tool to be the middle layer to the parts that depend on each editor. This design makes it easy to view diagnostics from tests in any editor. Environment-dependent features like neotest and VSCode's built-in testing tools can also be achieved with minimal code using testing-language-server. +## Instllation + +```sh +cargo install testing-language-server +cargo install testing-ls-adapter +``` + ## Features - [x] Realtime testing diagnostics - [ ] More efficient checking of diagnostics - [ ] Adapter installation command - [ ] VSCode extension -- [ ] Coc.nvim extension +- [x] Coc.nvim extension - [ ] NeoVim builtin LSP plugin ## Configuration @@ -63,14 +71,15 @@ language server config: ``` ## Adapter - -- [x] cargo test -- [x] jest -- [ ] others +- [x] `cargo test` +- [x] `cargo nextest` +- [x] `jest` +- [x] `deno test` +- [x] `go test` +- [x] `phpunit` +- [x] `vitest` ### Writing custom adapter ⚠ The specification of adapter CLI is not stabilized yet. -See [spec.rs](./src/spec.rs). - -[clap](https://docs.rs/clap) crate makes it easy to address specification, but in principle you can create an adapter in any way you like, regardless of the language you implement. +See [SPEC.md](./doc/SPEC.md) and [spec.rs](./src/spec.rs). From da2e46933702776c9e9e0ff6e677b9332a1fdabb Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 9 Oct 2024 09:07:41 +0900 Subject: [PATCH 061/139] fix: refresh workspace cache when it is empty --- src/server.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/server.rs b/src/server.rs index d924ef8..11faf84 100644 --- a/src/server.rs +++ b/src/server.rs @@ -213,6 +213,11 @@ impl TestingLS { Ok(()) } + /// Diagnoses the entire workspace for diagnostics. + /// This function will refresh the workspace cache, check if workspace diagnostics are enabled, + /// and then iterate through all workspaces to diagnose them. + /// It will trigger the publication of diagnostics for all files in the workspace + /// through the Language Server Protocol. pub fn diagnose_workspace(&mut self) -> Result { self.refresh_workspaces_cache()?; if !self.options.enable_workspace_diagnostics.unwrap_or(true) { @@ -249,12 +254,18 @@ impl TestingLS { Self::project_files(&base_dir, include_patterns, exclude_patterns) .contains(&path.to_owned()) }), - Err(_) => false, + Err(e) => { + tracing::error!("Error: {:?}", e); + false + } } } + /// Checks a specific file for diagnostics, optionally refreshing the workspace cache. + /// This function will trigger the publication of diagnostics for the specified file + /// through the Language Server Protocol. pub fn check_file(&mut self, path: &str, refresh_needed: bool) -> Result<(), LSError> { - if refresh_needed { + if refresh_needed || self.workspaces_cache.is_empty() { self.refresh_workspaces_cache()?; } self.workspaces_cache.iter().for_each( From 3d6b53ccdd9e9a57d747b87927a530afa22fdf3a Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 9 Oct 2024 09:08:19 +0900 Subject: [PATCH 062/139] docs: update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eb21e73..9f441d4 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ cargo install testing-ls-adapter - [x] Realtime testing diagnostics - [ ] More efficient checking of diagnostics - [ ] Adapter installation command -- [ ] VSCode extension -- [x] Coc.nvim extension +- [x] [VSCode extension](https://github.com/kbwo/vscode-testing-ls) +- [x] [Coc.nvim extension](https://github.com/kbwo/coc-testing-ls) - [ ] NeoVim builtin LSP plugin ## Configuration From b71ea060efd84dc7ee53a4c795fbeae4502dc790 Mon Sep 17 00:00:00 2001 From: kbwo Date: Thu, 10 Oct 2024 00:27:11 +0900 Subject: [PATCH 063/139] chore: update version --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acd5144..bfc5b16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -627,7 +627,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.9" +version = "0.0.10" dependencies = [ "anyhow", "clap", @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "testing-ls-adapter" -version = "0.0.5" +version = "0.0.6" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index 0186f45..e431c91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.9" +version = "0.0.10" edition = "2021" description = "LSP server for testing" license = "MIT" From 4e9f1b5c35ca35673cdf8e879227495b7519fded Mon Sep 17 00:00:00 2001 From: kbwo Date: Thu, 10 Oct 2024 00:28:51 +0900 Subject: [PATCH 064/139] chore(adapter): update version --- crates/adapter/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index b1abe8a..8028bd9 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.5" +version = "0.0.6" edition = "2021" description = "testing-language-server adapter" license = "MIT" From 7b59f5ae7489f6fe97ee1ad09c0be8898fee3f1f Mon Sep 17 00:00:00 2001 From: kbwo Date: Thu, 10 Oct 2024 00:35:40 +0900 Subject: [PATCH 065/139] ci: update release procedure --- .github/workflows/release-adapter.yml | 71 ++++++++++++++------- .github/workflows/release.yml | 91 ++++++++++++++++++--------- 2 files changed, 111 insertions(+), 51 deletions(-) diff --git a/.github/workflows/release-adapter.yml b/.github/workflows/release-adapter.yml index ad07ed0..718a50d 100644 --- a/.github/workflows/release-adapter.yml +++ b/.github/workflows/release-adapter.yml @@ -1,31 +1,60 @@ -name: Release +name: Release Adapter on: push: - tags: - - 'adapter-v*.*.*' + branches: + - main + paths: + - crates/adapter/Cargo.toml + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: - build: + check-version: + runs-on: ubuntu-latest + outputs: + version_changed: ${{ steps.check_version.outputs.version_changed }} + new_version: ${{ steps.check_version.outputs.new_version }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + - name: Check if version changed + id: check_version + run: | + PACKAGE_NAME=$(grep '^name' crates/adapter/Cargo.toml | sed 's/name = "\(.*\)"/\1/') + RELEASED_VERSION=$(cargo search $PACKAGE_NAME --limit 1 | grep -oP '(?<=").*(?=")') + if [ $? -ne 0 ]; then + echo "Failed to fetch released version" + exit 1 + fi + NEW_VERSION=$(grep '^version' crates/adapter/Cargo.toml | sed 's/version = "\(.*\)"/\1/') + + if [ "$RELEASED_VERSION" != "$NEW_VERSION" ]; then + echo "Version changed from $RELEASED_VERSION to $NEW_VERSION" + echo "version_changed=true" >> $GITHUB_OUTPUT + echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT + else + echo "No version change" + fi + + publish: + needs: check-version + if: needs.check-version.outputs.version_changed == 'true' runs-on: ubuntu-latest defaults: run: working-directory: crates/adapter - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - - name: Build project - run: cargo build --release - - - name: Publish to crates.io - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - run: cargo publish --token $CARGO_REGISTRY_TOKEN + - uses: actions/checkout@v3 + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - name: Publish to crates.io + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: cargo publish --token $CARGO_REGISTRY_TOKEN diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d4607e..e3fcc26 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,39 +1,70 @@ -name: Release +name: Auto Release on: push: - tags: - - 'v*.*.*' + branches: + - main + paths: + - Cargo.toml + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: - build: + check-version: runs-on: ubuntu-latest - + outputs: + version_changed: ${{ steps.check_version.outputs.version_changed }} + new_version: ${{ steps.check_version.outputs.new_version }} steps: - - name: Checkout code - uses: actions/checkout@v3 + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + - name: Check if version changed + id: check_version + run: | + PACKAGE_NAME=$(grep '^name' Cargo.toml | sed 's/name = "\(.*\)"/\1/') + RELEASED_VERSION=$(cargo search $PACKAGE_NAME --limit 1 | grep -oP '(?<=").*(?=")') + if [ $? -ne 0 ]; then + echo "Failed to fetch released version" + exit 1 + fi + NEW_VERSION=$(grep '^version' Cargo.toml | sed 's/version = "\(.*\)"/\1/') + + if [ "$RELEASED_VERSION" != "$NEW_VERSION" ]; then + echo "Version changed from $RELEASED_VERSION to $NEW_VERSION" + echo "version_changed=true" >> $GITHUB_OUTPUT + echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT + else + echo "No version change" + fi - - name: Set up Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true + create-release: + needs: check-version + if: needs.check-version.outputs.version_changed == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Create Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create v${{ needs.check-version.outputs.new_version }} \ + --title "Release ${{ needs.check-version.outputs.new_version }}" \ + --generate-notes - - name: Build project - run: cargo build --release - - # - name: Archive the build artifacts - # run: tar -czvf build.tar.gz -C target/release . - # - # - name: Create Release - # id: create_release - # uses: softprops/action-gh-release@v1 - # with: - # tag_name: ${{ github.ref }} - # files: build.tar.gz - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Publish to crates.io - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - run: cargo publish --token $CARGO_REGISTRY_TOKEN + publish: + needs: [check-version, create-release] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - name: Publish to crates.io + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: cargo publish --token $CARGO_REGISTRY_TOKEN From 13757136ba8580b5db7ede329a992ef7adca6c06 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 12 Oct 2024 17:16:37 +0900 Subject: [PATCH 066/139] feat: delete old server log files --- crates/adapter/src/log.rs | 9 +++++- src/log.rs | 19 +++++++++++-- src/util.rs | 58 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/crates/adapter/src/log.rs b/crates/adapter/src/log.rs index 7eefa83..c7d0363 100644 --- a/crates/adapter/src/log.rs +++ b/crates/adapter/src/log.rs @@ -1,11 +1,18 @@ +use std::path::PathBuf; + use tracing_appender::non_blocking::WorkerGuard; pub struct Log; impl Log { - pub fn init() -> Result { + fn log_dir() -> PathBuf { let home_dir = dirs::home_dir().unwrap(); let log_path = home_dir.join(".config/testing_language_server/adapter/logs"); + log_path + } + + pub fn init() -> Result { + let log_path = Self::log_dir(); let file_appender = tracing_appender::rolling::daily(log_path, "prefix.log"); let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); tracing_subscriber::fmt().with_writer(non_blocking).init(); diff --git a/src/log.rs b/src/log.rs index 9a0ec50..7626cae 100644 --- a/src/log.rs +++ b/src/log.rs @@ -1,13 +1,28 @@ +use crate::util::clean_old_logs; +use std::path::PathBuf; use tracing_appender::non_blocking::WorkerGuard; pub struct Log; impl Log { - pub fn init() -> Result { + fn log_dir() -> PathBuf { let home_dir = dirs::home_dir().unwrap(); let log_path = home_dir.join(".config/testing_language_server/logs"); - let file_appender = tracing_appender::rolling::daily(log_path, "prefix.log"); + log_path + } + + pub fn init() -> Result { + let log_dir_path = Self::log_dir(); + let prefix = "server.log"; + let file_appender = tracing_appender::rolling::daily(&log_dir_path, prefix); let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); + clean_old_logs( + log_dir_path.to_str().unwrap(), + 30, + "prefix.log.*", + "prefix.log.", + ) + .unwrap(); tracing_subscriber::fmt().with_writer(non_blocking).init(); Ok(guard) } diff --git a/src/util.rs b/src/util.rs index 04adad7..1ddc382 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,5 +1,8 @@ use crate::error::LSError; +use chrono::NaiveDate; +use chrono::Utc; use serde::Serialize; +use std::fs; use std::io::stdout; use std::io::Write; use std::path::Path; @@ -44,9 +47,39 @@ pub fn resolve_path(base_dir: &Path, relative_path: &str) -> PathBuf { PathBuf::from_iter(components) } +pub fn clean_old_logs( + log_dir: &str, + retention_days: i64, + glob_pattern: &str, + prefix: &str, +) -> Result<(), LSError> { + let today = Utc::now().date_naive(); + let retention_threshold = today - chrono::Duration::days(retention_days); + + let walker = globwalk::GlobWalkerBuilder::from_patterns(log_dir, &[glob_pattern]) + .build() + .unwrap(); + + for entry in walker.filter_map(Result::ok) { + let path = entry.path(); + if let Some(file_name) = path.file_name().and_then(|f| f.to_str()) { + if let Some(date_str) = file_name.strip_prefix(prefix) { + if let Ok(file_date) = NaiveDate::parse_from_str(date_str, "%Y-%m-%d") { + if file_date < retention_threshold { + fs::remove_file(path)?; + } + } + } + } + } + + Ok(()) +} + #[cfg(test)] mod tests { use super::*; + use std::fs::File; #[test] fn test_resolve_path() { @@ -100,4 +133,29 @@ mod tests { PathBuf::from("/Users/test/projects/bar/qux") ); } + + #[test] + fn test_clean_old_logs() { + let home_dir = dirs::home_dir().unwrap(); + let log_dir = home_dir.join(".config/testing_language_server/logs"); + + // Create test log files + let old_file = log_dir.join("prefix.log.2023-01-01"); + File::create(&old_file).unwrap(); + let recent_file = log_dir.join("prefix.log.2099-12-31"); + File::create(&recent_file).unwrap(); + let non_log_file = log_dir.join("not_a_log.txt"); + File::create(&non_log_file).unwrap(); + + // Run the clean_old_logs function + clean_old_logs(log_dir.to_str().unwrap(), 30, "prefix.log.*", "prefix.log.").unwrap(); + + // Check results + assert!(!old_file.exists(), "Old log file should be deleted"); + assert!( + recent_file.exists(), + "Recent log file should not be deleted" + ); + assert!(non_log_file.exists(), "Non-log file should not be deleted"); + } } From 96855b782c46993407cf3e0fb79addfe319f866a Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 12 Oct 2024 17:17:15 +0900 Subject: [PATCH 067/139] chore: change adapter config specification simplify key names --- .vim/coc-settings.json | 4 +- Cargo.lock | 153 ++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + demo/.vim/coc-settings.json | 31 ++++---- src/server.rs | 32 +++----- src/spec.rs | 6 +- 6 files changed, 186 insertions(+), 41 deletions(-) diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json index 1312f7e..910953d 100644 --- a/.vim/coc-settings.json +++ b/.vim/coc-settings.json @@ -6,8 +6,8 @@ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=cargo-test", "--workspace"], - "include_patterns": ["/**/*.rs"], - "exclude_patterns": ["/demo/**/*"], + "include": ["/**/*.rs"], + "exclude": ["/demo/**/*"], "workspace_dir": "." } ] diff --git a/Cargo.lock b/Cargo.lock index bfc5b16..5711706 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.13" @@ -65,6 +80,12 @@ version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bitflags" version = "1.3.2" @@ -87,6 +108,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "cc" version = "1.0.106" @@ -99,6 +126,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.5", +] + [[package]] name = "clap" version = "4.5.4" @@ -145,6 +186,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "crossbeam-channel" version = "0.5.12" @@ -287,6 +334,29 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.5.0" @@ -319,6 +389,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -378,6 +457,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -630,6 +718,7 @@ name = "testing-language-server" version = "0.0.10" dependencies = [ "anyhow", + "chrono", "clap", "dirs", "glob", @@ -906,6 +995,61 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + [[package]] name = "winapi-util" version = "0.1.8" @@ -915,6 +1059,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index e431c91..4fdf840 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,3 +47,4 @@ strum = { workspace = true, features = ["derive"] } glob = { workspace = true } globwalk = "0.9.1" tree-sitter-php = "0.22.8" +chrono = "0.4.38" diff --git a/demo/.vim/coc-settings.json b/demo/.vim/coc-settings.json index 4a72552..a332b62 100644 --- a/demo/.vim/coc-settings.json +++ b/demo/.vim/coc-settings.json @@ -10,59 +10,56 @@ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=cargo-test"], - "include_patterns": ["/**/src/**/*.rs"], - "exclude_patterns": ["/**/target/**"] + "include": ["/**/src/**/*.rs"], + "exclude": ["/**/target/**"] } ], "cargo-nextest": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=cargo-nextest"], - "include_patterns": ["/**/src/**/*.rs"], - "exclude_patterns": ["/**/target/**"] + "include": ["/**/src/**/*.rs"], + "exclude": ["/**/target/**"] } ], "jest": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=jest"], - "include_patterns": ["/jest/*.js"], - "exclude_patterns": ["/jest/**/node_modules/**/*"] + "include": ["/jest/*.js"], + "exclude": ["/jest/**/node_modules/**/*"] } ], "vitest": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=vitest"], - "include_patterns": [ - "/vitest/*.test.ts", - "/vitest/config/**/*.test.ts" - ], - "exclude_patterns": ["/vitest/**/node_modules/**/*"] + "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], + "exclude": ["/vitest/**/node_modules/**/*"] } ], "deno": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=deno"], - "include_patterns": ["/deno/*.ts"], - "exclude_patterns": [] + "include": ["/deno/*.ts"], + "exclude": [] } ], "go": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=go-test"], - "include_patterns": ["/**/*.go"], - "exclude_patterns": [] + "include": ["/**/*.go"], + "exclude": [] } ], "phpunit": [ { "path": "testing-ls-adapter", "extra_args": ["--test-kind=phpunit"], - "include_patterns": ["/**/*Test.php"], - "exclude_patterns": ["/phpunit/vendor/**/*.php"] + "include": ["/**/*Test.php"], + "exclude": ["/phpunit/vendor/**/*.php"] } ] } diff --git a/src/server.rs b/src/server.rs index 11faf84..c982f86 100644 --- a/src/server.rs +++ b/src/server.rs @@ -91,21 +91,17 @@ impl TestingLS { self.options.adapter_command.clone() } - fn project_files( - base_dir: &Path, - include_patterns: &[String], - exclude_patterns: &[String], - ) -> Vec { + fn project_files(base_dir: &Path, include: &[String], exclude: &[String]) -> Vec { let mut result: Vec = vec![]; - let exclude_pattern = exclude_patterns + let exclude_pattern = exclude .iter() .filter_map(|exclude_pattern| { Pattern::new(base_dir.join(exclude_pattern).to_str().unwrap()).ok() }) .collect::>(); let base_dir = base_dir.to_str().unwrap(); - let entries = globwalk::GlobWalkerBuilder::from_patterns(base_dir, include_patterns) + let entries = globwalk::GlobWalkerBuilder::from_patterns(base_dir, include) .follow_links(true) .build() .unwrap() @@ -159,14 +155,13 @@ impl TestingLS { let AdapterConfiguration { path, extra_args, - envs, - include_patterns, - exclude_patterns, + env, + include, + exclude, workspace_dir, .. } = &adapter; - let file_paths = - Self::project_files(&project_dir, include_patterns, exclude_patterns); + let file_paths = Self::project_files(&project_dir, include, exclude); if file_paths.is_empty() { continue; } @@ -181,7 +176,7 @@ impl TestingLS { .args(args_file_path) .arg("--") .args(extra_args) - .envs(envs) + .envs(env) .output() .map_err(|err| LSError::Adapter(err.to_string()))?; let adapter_result = String::from_utf8(output.stdout) @@ -241,8 +236,8 @@ impl TestingLS { let base_dir = self.project_dir(); match base_dir { Ok(base_dir) => self.workspaces_cache.iter().any(|cache| { - let include_patterns = &cache.adapter_config.include_patterns; - let exclude_patterns = &cache.adapter_config.exclude_patterns; + let include = &cache.adapter_config.include; + let exclude = &cache.adapter_config.exclude; if cache .workspaces .iter() @@ -251,8 +246,7 @@ impl TestingLS { return false; } - Self::project_files(&base_dir, include_patterns, exclude_patterns) - .contains(&path.to_owned()) + Self::project_files(&base_dir, include, exclude).contains(&path.to_owned()) }), Err(e) => { tracing::error!("Error: {:?}", e); @@ -305,7 +299,7 @@ impl TestingLS { .args(args) .arg("--") .args(&adapter.extra_args) - .envs(&adapter.envs) + .envs(&adapter.env) .output() .map_err(|err| LSError::Adapter(err.to_string()))?; let Output { stdout, stderr, .. } = output; @@ -450,7 +444,7 @@ impl TestingLS { .args(args) .arg("--") .args(&adapter.extra_args) - .envs(&adapter.envs) + .envs(&adapter.env) .output() .map_err(|err| LSError::Adapter(err.to_string()))?; diff --git a/src/spec.rs b/src/spec.rs index d159e4a..f342380 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -71,9 +71,9 @@ pub struct AdapterConfiguration { #[serde(default)] pub extra_args: Vec, #[serde(default)] - pub envs: HashMap, - pub include_patterns: Vec, - pub exclude_patterns: Vec, + pub env: HashMap, + pub include: Vec, + pub exclude: Vec, pub workspace_dir: Option, } From ab33121fc5c2141421f59c34725a1cc2277fcf93 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 12 Oct 2024 17:18:07 +0900 Subject: [PATCH 068/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5711706..653a482 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -715,7 +715,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.10" +version = "0.0.11" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 4fdf840..3885d5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.10" +version = "0.0.11" edition = "2021" description = "LSP server for testing" license = "MIT" From f2e2116683dd75a2470468f93c94eae3bc611c10 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 12 Oct 2024 17:20:38 +0900 Subject: [PATCH 069/139] ci: enable to pass test failed in CI --- src/util.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util.rs b/src/util.rs index 1ddc382..c076b4e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -138,6 +138,7 @@ mod tests { fn test_clean_old_logs() { let home_dir = dirs::home_dir().unwrap(); let log_dir = home_dir.join(".config/testing_language_server/logs"); + std::fs::create_dir_all(&log_dir).unwrap(); // Create test log files let old_file = log_dir.join("prefix.log.2023-01-01"); From f6aea922648c8726073b695cec8909ff2f9cc8a4 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 12 Oct 2024 17:30:49 +0900 Subject: [PATCH 070/139] feat(adapter): delete old adapter log files --- Cargo.lock | 10 ++++++---- crates/adapter/Cargo.toml | 2 +- crates/adapter/src/log.rs | 12 ++++++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 653a482..6ea1f1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -692,11 +692,10 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad25ceae0685a3744fb8ac2b1e096cab4b9c30649344051d4c238e546871291" +version = "0.0.11" dependencies = [ "anyhow", + "chrono", "clap", "dirs", "glob", @@ -711,11 +710,14 @@ dependencies = [ "tracing", "tracing-appender", "tracing-subscriber", + "tree-sitter-php", ] [[package]] name = "testing-language-server" version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c1a48aec4305834e4f80ad28dfe5bea8c98c0bb215a092eb2af15c4ac86efb7" dependencies = [ "anyhow", "chrono", @@ -748,7 +750,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.0.6", + "testing-language-server 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 8028bd9..3e2ed37 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -testing-language-server = "0.0.6" +testing-language-server = "0.0.11" lsp-types = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } diff --git a/crates/adapter/src/log.rs b/crates/adapter/src/log.rs index c7d0363..792abdd 100644 --- a/crates/adapter/src/log.rs +++ b/crates/adapter/src/log.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; +use testing_language_server::util::clean_old_logs; use tracing_appender::non_blocking::WorkerGuard; pub struct Log; @@ -12,9 +13,16 @@ impl Log { } pub fn init() -> Result { - let log_path = Self::log_dir(); - let file_appender = tracing_appender::rolling::daily(log_path, "prefix.log"); + let log_dir_path = Self::log_dir(); + let file_appender = tracing_appender::rolling::daily(&log_dir_path, "prefix.log"); let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); + clean_old_logs( + log_dir_path.to_str().unwrap(), + 30, + "prefix.log.*", + "prefix.log.", + ) + .unwrap(); tracing_subscriber::fmt().with_writer(non_blocking).init(); Ok(guard) } From b399d226563640f5f406314f188624069dfbd53a Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 12 Oct 2024 17:32:59 +0900 Subject: [PATCH 071/139] fix: rename log file name --- crates/adapter/src/log.rs | 7 ++++--- src/log.rs | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/adapter/src/log.rs b/crates/adapter/src/log.rs index 792abdd..6a17a5a 100644 --- a/crates/adapter/src/log.rs +++ b/crates/adapter/src/log.rs @@ -14,13 +14,14 @@ impl Log { pub fn init() -> Result { let log_dir_path = Self::log_dir(); - let file_appender = tracing_appender::rolling::daily(&log_dir_path, "prefix.log"); + let prefix = "adapter.log"; + let file_appender = tracing_appender::rolling::daily(&log_dir_path, prefix); let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); clean_old_logs( log_dir_path.to_str().unwrap(), 30, - "prefix.log.*", - "prefix.log.", + &format!("{prefix}.*"), + &format!("{prefix}."), ) .unwrap(); tracing_subscriber::fmt().with_writer(non_blocking).init(); diff --git a/src/log.rs b/src/log.rs index 7626cae..2949f46 100644 --- a/src/log.rs +++ b/src/log.rs @@ -19,8 +19,8 @@ impl Log { clean_old_logs( log_dir_path.to_str().unwrap(), 30, - "prefix.log.*", - "prefix.log.", + &format!("{prefix}.*"), + &format!("{prefix}."), ) .unwrap(); tracing_subscriber::fmt().with_writer(non_blocking).init(); From dfd017c5d3c640cbd13a09fed3e7eb1d6c082980 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 12 Oct 2024 17:33:29 +0900 Subject: [PATCH 072/139] chore: update version --- Cargo.lock | 50 +++++++++++++++++++-------------------- Cargo.toml | 2 +- crates/adapter/Cargo.toml | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ea1f1d..a2b0db3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -690,29 +690,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "testing-language-server" -version = "0.0.11" -dependencies = [ - "anyhow", - "chrono", - "clap", - "dirs", - "glob", - "globwalk", - "lsp-types", - "once_cell", - "regex", - "serde", - "serde_json", - "strum", - "thiserror", - "tracing", - "tracing-appender", - "tracing-subscriber", - "tree-sitter-php", -] - [[package]] name = "testing-language-server" version = "0.0.11" @@ -738,9 +715,32 @@ dependencies = [ "tree-sitter-php", ] +[[package]] +name = "testing-language-server" +version = "0.0.12" +dependencies = [ + "anyhow", + "chrono", + "clap", + "dirs", + "glob", + "globwalk", + "lsp-types", + "once_cell", + "regex", + "serde", + "serde_json", + "strum", + "thiserror", + "tracing", + "tracing-appender", + "tracing-subscriber", + "tree-sitter-php", +] + [[package]] name = "testing-ls-adapter" -version = "0.0.6" +version = "0.0.7" dependencies = [ "anyhow", "clap", @@ -750,7 +750,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "testing-language-server 0.0.11", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 3885d5c..bc873b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.11" +version = "0.0.12" edition = "2021" description = "LSP server for testing" license = "MIT" diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 3e2ed37..ee0a4c5 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.6" +version = "0.0.7" edition = "2021" description = "testing-language-server adapter" license = "MIT" From 7935caf4b3587612b084a0c9efcf4cf83ddb4d25 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 13 Oct 2024 23:41:33 +0900 Subject: [PATCH 073/139] chore: update specification --- .vim/coc-settings.json | 2 +- README.md | 14 ++++++++------ demo/.vim/coc-settings.json | 14 +++++++------- demo/.vscode/settings.json | 12 ++++++------ src/server.rs | 12 ++++++------ src/spec.rs | 2 +- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json index 910953d..cd55328 100644 --- a/.vim/coc-settings.json +++ b/.vim/coc-settings.json @@ -5,7 +5,7 @@ "rust": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=cargo-test", "--workspace"], + "extra_arg": ["--test-kind=cargo-test", "--workspace"], "include": ["/**/*.rs"], "exclude": ["/demo/**/*"], "workspace_dir": "." diff --git a/README.md b/README.md index 9f441d4..2e2777f 100644 --- a/README.md +++ b/README.md @@ -50,17 +50,17 @@ language server config: "cargo test": [ { "path": "/testing-ls-adapter", - "extra_args": ["--test-kind=cargo-test"], - "include_pattern": ["**/*.rs"], - "exclude_pattern": ["**/target/**"] + "extra_arg": ["--test-kind=cargo-test"], + "include": ["**/*.rs"], + "exclude": ["**/target/**"] } ], "jest": [ { "path": "/testing-ls-adapter", - "extra_args": ["--test-kind=jest"], - "include_patterns": ["/**/*.js"], - "exclude_patterns": ["/node_modules/**/*"] + "extra_arg": ["--test-kind=jest"], + "include": ["/**/*.js"], + "exclude": ["/node_modules/**/*"] } ] } @@ -70,6 +70,8 @@ language server config: } ``` +[See more example](./demo/.vim/coc-settings.json) + ## Adapter - [x] `cargo test` - [x] `cargo nextest` diff --git a/demo/.vim/coc-settings.json b/demo/.vim/coc-settings.json index a332b62..8558366 100644 --- a/demo/.vim/coc-settings.json +++ b/demo/.vim/coc-settings.json @@ -9,7 +9,7 @@ "cargo-test": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=cargo-test"], + "extra_arg": ["--test-kind=cargo-test"], "include": ["/**/src/**/*.rs"], "exclude": ["/**/target/**"] } @@ -17,7 +17,7 @@ "cargo-nextest": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=cargo-nextest"], + "extra_arg": ["--test-kind=cargo-nextest"], "include": ["/**/src/**/*.rs"], "exclude": ["/**/target/**"] } @@ -25,7 +25,7 @@ "jest": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=jest"], + "extra_arg": ["--test-kind=jest"], "include": ["/jest/*.js"], "exclude": ["/jest/**/node_modules/**/*"] } @@ -33,7 +33,7 @@ "vitest": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=vitest"], + "extra_arg": ["--test-kind=vitest"], "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], "exclude": ["/vitest/**/node_modules/**/*"] } @@ -41,7 +41,7 @@ "deno": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=deno"], + "extra_arg": ["--test-kind=deno"], "include": ["/deno/*.ts"], "exclude": [] } @@ -49,7 +49,7 @@ "go": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=go-test"], + "extra_arg": ["--test-kind=go-test"], "include": ["/**/*.go"], "exclude": [] } @@ -57,7 +57,7 @@ "phpunit": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=phpunit"], + "extra_arg": ["--test-kind=phpunit"], "include": ["/**/*Test.php"], "exclude": ["/phpunit/vendor/**/*.php"] } diff --git a/demo/.vscode/settings.json b/demo/.vscode/settings.json index 442dcda..37ba4f8 100644 --- a/demo/.vscode/settings.json +++ b/demo/.vscode/settings.json @@ -5,7 +5,7 @@ "cargo-nextest": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=cargo-nextest"], + "extra_arg": ["--test-kind=cargo-nextest"], "include_patterns": ["/**/src/**/*.rs"], "exclude_patterns": ["/**/target/**"] } @@ -13,7 +13,7 @@ "jest": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=jest"], + "extra_arg": ["--test-kind=jest"], "include_patterns": ["/jest/*.js"], "exclude_patterns": ["/jest/**/node_modules/**/*"] } @@ -21,7 +21,7 @@ "vitest": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=vitest"], + "extra_arg": ["--test-kind=vitest"], "include_patterns": [ "/vitest/*.test.ts", "/vitest/config/**/*.test.ts" @@ -32,7 +32,7 @@ "deno": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=deno"], + "extra_arg": ["--test-kind=deno"], "include_patterns": ["/deno/*.ts"], "exclude_patterns": [] } @@ -40,7 +40,7 @@ "go": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=go-test"], + "extra_arg": ["--test-kind=go-test"], "include_patterns": ["/**/*.go"], "exclude_patterns": [] } @@ -48,7 +48,7 @@ "phpunit": [ { "path": "testing-ls-adapter", - "extra_args": ["--test-kind=phpunit"], + "extra_arg": ["--test-kind=phpunit"], "include_patterns": ["/**/*Test.php"], "exclude_patterns": ["/phpunit/vendor/**/*.php"] } diff --git a/src/server.rs b/src/server.rs index c982f86..1eea50e 100644 --- a/src/server.rs +++ b/src/server.rs @@ -154,7 +154,7 @@ impl TestingLS { for adapter in adapter_commands.into_iter() { let AdapterConfiguration { path, - extra_args, + extra_arg, env, include, exclude, @@ -175,7 +175,7 @@ impl TestingLS { .arg("detect-workspace") .args(args_file_path) .arg("--") - .args(extra_args) + .args(extra_arg) .envs(env) .output() .map_err(|err| LSError::Adapter(err.to_string()))?; @@ -298,7 +298,7 @@ impl TestingLS { .arg("run-file-test") .args(args) .arg("--") - .args(&adapter.extra_args) + .args(&adapter.extra_arg) .envs(&adapter.env) .output() .map_err(|err| LSError::Adapter(err.to_string()))?; @@ -443,7 +443,7 @@ impl TestingLS { .arg("discover") .args(args) .arg("--") - .args(&adapter.extra_args) + .args(&adapter.extra_arg) .envs(&adapter.env) .output() .map_err(|err| LSError::Adapter(err.to_string()))?; @@ -510,7 +510,7 @@ mod tests { .unwrap(); let adapter_conf = AdapterConfiguration { path: abs_path_of_rust_adapter, - extra_args: vec!["--test-kind=cargo-test".to_string()], + extra_arg: vec!["--test-kind=cargo-test".to_string()], ..Default::default() }; let mut server = TestingLS { @@ -571,7 +571,7 @@ mod tests { .to_str() .unwrap() .to_string(), - extra_args: vec!["--invalid-arg".to_string()], + extra_arg: vec!["--invalid-arg".to_string()], ..Default::default() }; let abs_path_of_demo = std::env::current_dir().unwrap().join("demo/rust"); diff --git a/src/spec.rs b/src/spec.rs index f342380..06d2f6f 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -69,7 +69,7 @@ impl WorkspaceAnalysis { pub struct AdapterConfiguration { pub path: String, #[serde(default)] - pub extra_args: Vec, + pub extra_arg: Vec, #[serde(default)] pub env: HashMap, pub include: Vec, From 3d01eef6b18fd3858017e3c10b7114fce1e8413e Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 14 Oct 2024 00:00:34 +0900 Subject: [PATCH 074/139] chore(adapter): add tracing logs --- crates/adapter/src/runner/cargo_nextest.rs | 7 +++++-- crates/adapter/src/runner/cargo_test.rs | 7 +++++-- crates/adapter/src/runner/deno.rs | 7 +++++-- crates/adapter/src/runner/go.rs | 7 +++++-- crates/adapter/src/runner/jest.rs | 7 +++++-- crates/adapter/src/runner/phpunit.rs | 7 +++++-- crates/adapter/src/runner/util.rs | 10 +++++----- crates/adapter/src/runner/vitest.rs | 7 +++++-- 8 files changed, 40 insertions(+), 19 deletions(-) diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index 2913155..fea1680 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -11,7 +11,7 @@ use testing_language_server::spec::DiscoverResultItem; use crate::model::Runner; -use super::util::detect_workspaces_from_file_paths; +use super::util::detect_workspaces_from_file_list; use super::util::discover_rust_tests; use super::util::parse_cargo_diagnostics; use super::util::write_result_log; @@ -25,13 +25,14 @@ fn parse_diagnostics( } fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { - detect_workspaces_from_file_paths(file_paths, &["Cargo.toml".to_string()]) + detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]) } #[derive(Eq, PartialEq, Hash, Debug)] pub struct CargoNextestRunner; impl Runner for CargoNextestRunner { + #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; @@ -47,6 +48,7 @@ impl Runner for CargoNextestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn run_file_test( &self, args: testing_language_server::spec::RunFileTestArgs, @@ -98,6 +100,7 @@ impl Runner for CargoNextestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index bfd02d9..3834c3c 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -11,7 +11,7 @@ use testing_language_server::spec::DiscoverResultItem; use crate::model::Runner; -use super::util::detect_workspaces_from_file_paths; +use super::util::detect_workspaces_from_file_list; use super::util::discover_rust_tests; use super::util::parse_cargo_diagnostics; use super::util::write_result_log; @@ -25,13 +25,14 @@ fn parse_diagnostics( } fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { - detect_workspaces_from_file_paths(file_paths, &["Cargo.toml".to_string()]) + detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]) } #[derive(Eq, PartialEq, Hash, Debug)] pub struct CargoTestRunner; impl Runner for CargoTestRunner { + #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; @@ -47,6 +48,7 @@ impl Runner for CargoTestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn run_file_test( &self, args: testing_language_server::spec::RunFileTestArgs, @@ -90,6 +92,7 @@ impl Runner for CargoTestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index 9db0735..d85fe5b 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -21,7 +21,7 @@ use testing_language_server::spec::TestItem; use crate::model::Runner; use super::util::clean_ansi; -use super::util::detect_workspaces_from_file_paths; +use super::util::detect_workspaces_from_file_list; use super::util::discover_with_treesitter; use super::util::write_result_log; use super::util::MAX_CHAR_LENGTH; @@ -96,7 +96,7 @@ fn parse_diagnostics( } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - detect_workspaces_from_file_paths(&file_paths, &["deno.json".to_string()]) + detect_workspaces_from_file_list(&file_paths, &["deno.json".to_string()]) } fn discover(file_path: &str) -> Result, LSError> { @@ -158,6 +158,7 @@ fn discover(file_path: &str) -> Result, LSError> { pub struct DenoRunner; impl Runner for DenoRunner { + #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; @@ -171,6 +172,7 @@ impl Runner for DenoRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn run_file_test( &self, args: testing_language_server::spec::RunFileTestArgs, @@ -198,6 +200,7 @@ impl Runner for DenoRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 86638e4..6ba3a1d 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -18,7 +18,7 @@ use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::RunFileTestResultItem; use testing_language_server::spec::TestItem; -use super::util::detect_workspaces_from_file_paths; +use super::util::detect_workspaces_from_file_list; use super::util::discover_with_treesitter; use super::util::write_result_log; use super::util::MAX_CHAR_LENGTH; @@ -226,6 +226,7 @@ fn discover(file_path: &str) -> Result, LSError> { #[derive(Eq, PartialEq, Hash, Debug)] pub struct GoTestRunner; impl Runner for GoTestRunner { + #[tracing::instrument(skip(self))] fn discover( &self, args: testing_language_server::spec::DiscoverArgs, @@ -244,6 +245,7 @@ impl Runner for GoTestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn run_file_test( &self, args: testing_language_server::spec::RunFileTestArgs, @@ -273,11 +275,12 @@ impl Runner for GoTestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, ) -> Result<(), testing_language_server::error::LSError> { - send_stdout(&detect_workspaces_from_file_paths( + send_stdout(&detect_workspaces_from_file_list( &args.file_paths, &["go.mod".to_string()], ))?; diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index b9e8125..f8b2a92 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -16,7 +16,7 @@ use testing_language_server::spec::TestItem; use crate::model::Runner; use super::util::clean_ansi; -use super::util::detect_workspaces_from_file_paths; +use super::util::detect_workspaces_from_file_list; use super::util::discover_with_treesitter; use super::util::LOG_LOCATION; use super::util::MAX_CHAR_LENGTH; @@ -74,7 +74,7 @@ fn parse_diagnostics( } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - detect_workspaces_from_file_paths(&file_paths, &["package.json".to_string()]) + detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]) } fn discover(file_path: &str) -> Result, LSError> { @@ -156,6 +156,7 @@ fn discover(file_path: &str) -> Result, LSError> { pub struct JestRunner; impl Runner for JestRunner { + #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; @@ -169,6 +170,7 @@ impl Runner for JestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn run_file_test( &self, args: testing_language_server::spec::RunFileTestArgs, @@ -195,6 +197,7 @@ impl Runner for JestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, diff --git a/crates/adapter/src/runner/phpunit.rs b/crates/adapter/src/runner/phpunit.rs index 18f3c26..c54dc7b 100644 --- a/crates/adapter/src/runner/phpunit.rs +++ b/crates/adapter/src/runner/phpunit.rs @@ -12,7 +12,7 @@ use xml::reader::{ParserConfig, XmlEvent}; use crate::model::Runner; use super::util::{ - detect_workspaces_from_file_paths, discover_with_treesitter, send_stdout, LOG_LOCATION, + detect_workspaces_from_file_list, discover_with_treesitter, send_stdout, LOG_LOCATION, MAX_CHAR_LENGTH, }; @@ -47,7 +47,7 @@ impl Into for ResultFromXml { } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - detect_workspaces_from_file_paths(&file_paths, &["composer.json".to_string()]) + detect_workspaces_from_file_list(&file_paths, &["composer.json".to_string()]) } fn get_result_from_characters(characters: &str) -> Result { @@ -152,6 +152,7 @@ fn discover(file_path: &str) -> Result, LSError> { pub struct PhpunitRunner; impl Runner for PhpunitRunner { + #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; @@ -165,6 +166,7 @@ impl Runner for PhpunitRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn run_file_test( &self, args: testing_language_server::spec::RunFileTestArgs, @@ -216,6 +218,7 @@ impl Runner for PhpunitRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index deeee1d..b61894e 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -21,7 +21,7 @@ pub static LOG_LOCATION: LazyLock = LazyLock::new(|| { pub const MAX_CHAR_LENGTH: u32 = 10000; /// determine if a particular file is the root of workspace based on whether it is in the same directory -pub fn detect_workspace_from_file(file_path: PathBuf, file_names: &[String]) -> Option { +fn detect_workspace_from_file(file_path: PathBuf, file_names: &[String]) -> Option { let parent = file_path.parent(); if let Some(parent) = parent { if file_names @@ -37,7 +37,7 @@ pub fn detect_workspace_from_file(file_path: PathBuf, file_names: &[String]) -> } } -pub fn detect_workspaces_from_file_paths( +pub fn detect_workspaces_from_file_list( target_file_paths: &[String], file_names: &[String], ) -> HashMap> { @@ -54,9 +54,9 @@ pub fn detect_workspaces_from_file_paths( .or_default() .push(file_path.clone()); } - // Push the file path to the found workspace even if the existing_workspace becomes Some. - // In some cases, the simple method of finding a workspace, such as the relationship - // between the project root and the adapter crate in this repository, does not work. + // Push the file path to the found workspace even if existing_workspace becomes Some. + // In some cases, a simple way to find a workspace, + // such as the relationship between the project root and the adapter crate in this repository, may not work. let workspace = detect_workspace_from_file(PathBuf::from_str(&file_path).unwrap(), file_names); if let Some(workspace) = workspace { diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index b8226f7..225b22c 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -15,7 +15,7 @@ use testing_language_server::{ use crate::model::Runner; use super::util::{ - clean_ansi, detect_workspaces_from_file_paths, discover_with_treesitter, send_stdout, + clean_ansi, detect_workspaces_from_file_list, discover_with_treesitter, send_stdout, LOG_LOCATION, MAX_CHAR_LENGTH, }; @@ -131,6 +131,7 @@ fn parse_diagnostics( } impl Runner for VitestRunner { + #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = vec![]; @@ -146,6 +147,7 @@ impl Runner for VitestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn run_file_test( &self, args: testing_language_server::spec::RunFileTestArgs, @@ -170,11 +172,12 @@ impl Runner for VitestRunner { Ok(()) } + #[tracing::instrument(skip(self))] fn detect_workspaces( &self, args: testing_language_server::spec::DetectWorkspaceArgs, ) -> Result<(), LSError> { - send_stdout(&detect_workspaces_from_file_paths( + send_stdout(&detect_workspaces_from_file_list( &args.file_paths, &[ "package.json".to_string(), From 54c3ca3e298733891f3a64de7488b28ec73f6685 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 14 Oct 2024 00:00:56 +0900 Subject: [PATCH 075/139] docs: update README --- README.md | 8 ++++---- demo/README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 demo/README.md diff --git a/README.md b/README.md index 2e2777f..8ee4b62 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This LSP server is heavily influenced by the following tools - [neotest](https://github.com/nvim-neotest/neotest) - [Wallaby.js](https://wallabyjs.com) -These tools are very useful and powerful. However, they depend on the execution environment, such as VSCode and NeoVim, and the portability aspect was inconvenient for me. +These tools are very useful and powerful. However, they depend on the execution environment, such as VSCode and Neovim, and the portability aspect was inconvenient for me. So, I designed this testing-language-server and its dedicated adapters for each test tool to be the middle layer to the parts that depend on each editor. This design makes it easy to view diagnostics from tests in any editor. Environment-dependent features like neotest and VSCode's built-in testing tools can also be achieved with minimal code using testing-language-server. @@ -25,11 +25,11 @@ cargo install testing-ls-adapter ## Features - [x] Realtime testing diagnostics -- [ ] More efficient checking of diagnostics -- [ ] Adapter installation command - [x] [VSCode extension](https://github.com/kbwo/vscode-testing-ls) - [x] [Coc.nvim extension](https://github.com/kbwo/coc-testing-ls) -- [ ] NeoVim builtin LSP plugin +- [x] For Neovim builtin LSP, see [demo/README.md](./demo/README.md) +- [ ] More efficient checking of diagnostics +- [ ] Useful commands in each extension ## Configuration diff --git a/demo/README.md b/demo/README.md new file mode 100644 index 0000000..f168592 --- /dev/null +++ b/demo/README.md @@ -0,0 +1,43 @@ +## Using `nvim-lspconfig` + +The specification is not stable, so you need to set it yourself. Once the spec is stable, I will send a PR to `nvim-lspconfig`. +``` +local lspconfig = require('lspconfig') +local configs = require('lspconfig.configs') +local util = require "lspconfig/util" + +configs.testing_ls = { + default_config = { + cmd = { "testing-language-server" }, + filetypes = { "rust" }, + root_dir = util.root_pattern(".git", "Cargo.toml"), + init_options = { + enable = true, + fileTypes = {"rust"}, + adapterCommand = { + rust = { + { + path = "testing-ls-adapter", + extra_arg = { "--test-kind=cargo-test", "--workspace" }, + include = { "/demo/**/src/**/*.rs"}, + exclude = { "/**/target/**"}, + } + } + }, + enableWorkspaceDiagnostics = true, + trace = { + server = "verbose" + } + } + }, + docs = { + description = [[ + https://github.com/kbwo/testing-language-server + + Language Server for real-time testing. + ]], + }, +} + +lspconfig.testing_ls.setup{} +``` From aee202b9d1a8f164475431c00f46c97bc762b603 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 14 Oct 2024 00:01:24 +0900 Subject: [PATCH 076/139] chore: update versions --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/adapter/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a2b0db3..4fb6f6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,7 +717,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.12" +version = "0.0.13" dependencies = [ "anyhow", "chrono", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "testing-ls-adapter" -version = "0.0.7" +version = "0.0.8" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index bc873b7..01e0353 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.12" +version = "0.0.13" edition = "2021" description = "LSP server for testing" license = "MIT" diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index ee0a4c5..44c0122 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.7" +version = "0.0.8" edition = "2021" description = "testing-language-server adapter" license = "MIT" From 46a9d12823e831a0e77abb9b4e2f4199f58704a6 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 14 Oct 2024 21:45:50 +0900 Subject: [PATCH 077/139] fix: handle shutdown correctly according to specification Specification: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#shutdown --- src/server.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server.rs b/src/server.rs index 1eea50e..c1daa4d 100644 --- a/src/server.rs +++ b/src/server.rs @@ -467,7 +467,7 @@ impl TestingLS { send_stdout(&json!({ "jsonrpc": "2.0", "id": id, - "method": json!(null), + "result": null }))?; Ok(()) } @@ -614,4 +614,4 @@ mod tests { let status = server.diagnose_workspace().unwrap(); assert_eq!(status, WorkspaceDiagnosticsStatus::Skipped); } -} +} \ No newline at end of file From 570a755e50b2cd99cb1347f69a1a1e7fe1fb1289 Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 14 Oct 2024 21:46:50 +0900 Subject: [PATCH 078/139] chore(demo): update vscode settings --- demo/.vscode/settings.json | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/demo/.vscode/settings.json b/demo/.vscode/settings.json index 37ba4f8..3252c69 100644 --- a/demo/.vscode/settings.json +++ b/demo/.vscode/settings.json @@ -6,51 +6,48 @@ { "path": "testing-ls-adapter", "extra_arg": ["--test-kind=cargo-nextest"], - "include_patterns": ["/**/src/**/*.rs"], - "exclude_patterns": ["/**/target/**"] + "include": ["/**/src/**/*.rs"], + "exclude": ["/**/target/**"] } ], "jest": [ { "path": "testing-ls-adapter", "extra_arg": ["--test-kind=jest"], - "include_patterns": ["/jest/*.js"], - "exclude_patterns": ["/jest/**/node_modules/**/*"] + "include": ["/jest/*.js"], + "exclude": ["/jest/**/node_modules/**/*"] } ], "vitest": [ { "path": "testing-ls-adapter", "extra_arg": ["--test-kind=vitest"], - "include_patterns": [ - "/vitest/*.test.ts", - "/vitest/config/**/*.test.ts" - ], - "exclude_patterns": ["/vitest/**/node_modules/**/*"] + "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], + "exclude": ["/vitest/**/node_modules/**/*"] } ], "deno": [ { "path": "testing-ls-adapter", "extra_arg": ["--test-kind=deno"], - "include_patterns": ["/deno/*.ts"], - "exclude_patterns": [] + "include": ["/deno/*.ts"], + "exclude": [] } ], "go": [ { "path": "testing-ls-adapter", "extra_arg": ["--test-kind=go-test"], - "include_patterns": ["/**/*.go"], - "exclude_patterns": [] + "include": ["/**/*.go"], + "exclude": [] } ], "phpunit": [ { "path": "testing-ls-adapter", "extra_arg": ["--test-kind=phpunit"], - "include_patterns": ["/**/*Test.php"], - "exclude_patterns": ["/phpunit/vendor/**/*.php"] + "include": ["/**/*Test.php"], + "exclude": ["/phpunit/vendor/**/*.php"] } ] }, From 2bc6a5acf383084a8a3837bd2c03cdd000b7607f Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 14 Oct 2024 21:47:16 +0900 Subject: [PATCH 079/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4fb6f6b..1690510 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,7 +717,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.13" +version = "0.0.14" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 01e0353..d1a81bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.13" +version = "0.0.14" edition = "2021" description = "LSP server for testing" license = "MIT" From 4bb5144e0c78715c1fdf317c4ae38f3fe8599ef1 Mon Sep 17 00:00:00 2001 From: sho-hata Date: Thu, 17 Oct 2024 08:08:42 +0900 Subject: [PATCH 080/139] docs: update adapter specification link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ee4b62..12aa099 100644 --- a/README.md +++ b/README.md @@ -84,4 +84,4 @@ language server config: ### Writing custom adapter ⚠ The specification of adapter CLI is not stabilized yet. -See [SPEC.md](./doc/SPEC.md) and [spec.rs](./src/spec.rs). +See [ADAPTER_SPEC.md](./doc/ADAPTER_SPEC.md) and [spec.rs](./src/spec.rs). From d275c28e887918aa6713826eac1abe3da5a0c27c Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 16 Oct 2024 23:58:41 +0900 Subject: [PATCH 081/139] chore(demo): add demo code of `node --test` --- demo/node-test/index.test.js | 167 +++++++++++++++++++ demo/node-test/output.xml | 307 +++++++++++++++++++++++++++++++++++ demo/node-test/package.json | 12 ++ 3 files changed, 486 insertions(+) create mode 100644 demo/node-test/index.test.js create mode 100644 demo/node-test/output.xml create mode 100644 demo/node-test/package.json diff --git a/demo/node-test/index.test.js b/demo/node-test/index.test.js new file mode 100644 index 0000000..54013b2 --- /dev/null +++ b/demo/node-test/index.test.js @@ -0,0 +1,167 @@ +const test = require("node:test"); +const { describe, it } = require("node:test"); +// # Basic example +test("synchronous passing test", (t) => { + // This test passes because it does not throw an exception. + assert.strictEqual(1, 1); +}); + +test("synchronous failing test", (t) => { + // This test fails because it throws an exception. + assert.strictEqual(1, 2); +}); + +test("asynchronous passing test", async (t) => { + // This test passes because the Promise returned by the async + // function is settled and not rejected. + assert.strictEqual(1, 1); +}); + +test("asynchronous failing test", async (t) => { + // This test fails because the Promise returned by the async + // function is rejected. + assert.strictEqual(1, 2); +}); + +test("failing test using Promises", (t) => { + // Promises can be used directly as well. + return new Promise((resolve, reject) => { + setImmediate(() => { + reject(new Error("this will cause the test to fail")); + }); + }); +}); + +test("callback passing test", (t, done) => { + // done() is the callback function. When the setImmediate() runs, it invokes + // done() with no arguments. + setImmediate(done); +}); + +test("callback failing test", (t, done) => { + // When the setImmediate() runs, done() is invoked with an Error object and + // the test fails. + setImmediate(() => { + done(new Error("callback failure")); + }); +}); + +// # Subtests +test("top level test", async (t) => { + await t.test("subtest 1", (t) => { + assert.strictEqual(1, 1); + }); + + await t.test("subtest 2", (t) => { + assert.strictEqual(2, 2); + }); +}); + +// # Skipping tests +// The skip option is used, but no message is provided. +test("skip option", { skip: true }, (t) => { + // This code is never executed. +}); + +// The skip option is used, and a message is provided. +test("skip option with message", { skip: "this is skipped" }, (t) => { + // This code is never executed. +}); + +test("skip() method", (t) => { + // Make sure to return here as well if the test contains additional logic. + t.skip(); +}); + +test("skip() method with message", (t) => { + // Make sure to return here as well if the test contains additional logic. + t.skip("this is skipped"); +}); + +// # TODO tests +// The todo option is used, but no message is provided. +test("todo option", { todo: true }, (t) => { + // This code is executed, but not treated as a failure. + throw new Error("this does not fail the test"); +}); + +// The todo option is used, and a message is provided. +test("todo option with message", { todo: "this is a todo test" }, (t) => { + // This code is executed. +}); + +test("todo() method", (t) => { + t.todo(); +}); + +test("todo() method with message", (t) => { + t.todo("this is a todo test and is not treated as a failure"); + throw new Error("this does not fail the test"); +}); + +// # describe() and it() aliases +describe("A thing", () => { + it("should work", () => { + assert.strictEqual(1, 1); + }); + + it("should be ok", () => { + assert.strictEqual(2, 2); + }); + + describe("a nested thing", () => { + it("should work", () => { + assert.strictEqual(3, 3); + }); + }); +}); + +// # only tests +// Assume Node.js is run with the --test-only command-line option. +// The suite's 'only' option is set, so these tests are run. +test("this test is run", { only: true }, async (t) => { + // Within this test, all subtests are run by default. + await t.test("running subtest"); + + // The test context can be updated to run subtests with the 'only' option. + t.runOnly(true); + await t.test("this subtest is now skipped"); + await t.test("this subtest is run", { only: true }); + + // Switch the context back to execute all tests. + t.runOnly(false); + await t.test("this subtest is now run"); + + // Explicitly do not run these tests. + await t.test("skipped subtest 3", { only: false }); + await t.test("skipped subtest 4", { skip: true }); +}); + +// The 'only' option is not set, so this test is skipped. +test("this test is not run", () => { + // This code is not run. + throw new Error("fail"); +}); + +describe("a suite", () => { + // The 'only' option is set, so this test is run. + it("this test is run", { only: true }, () => { + // This code is run. + }); + + it("this test is not run", () => { + // This code is not run. + throw new Error("fail"); + }); +}); + +describe.only("a suite", () => { + // The 'only' option is set, so this test is run. + it("this test is run", () => { + // This code is run. + }); + + it("this test is run", () => { + // This code is run. + }); +}); diff --git a/demo/node-test/output.xml b/demo/node-test/output.xml new file mode 100644 index 0000000..6e342ed --- /dev/null +++ b/demo/node-test/output.xml @@ -0,0 +1,307 @@ + + + + +[Error [ERR_TEST_FAILURE]: assert is not defined] { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:6:3) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.start (node:internal/test_runner/test:542:17) + at startSubtest (node:internal/test_runner/harness:214:17), + code: 'ERR_TEST_FAILURE' +} + + + + +[Error [ERR_TEST_FAILURE]: assert is not defined] { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:11:3) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19) + at Test.run (node:internal/test_runner/test:673:12) + at async startSubtest (node:internal/test_runner/harness:214:3), + code: 'ERR_TEST_FAILURE' +} + + + + +[Error [ERR_TEST_FAILURE]: assert is not defined] { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:17:3) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19) + at Test.run (node:internal/test_runner/test:673:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + +[Error [ERR_TEST_FAILURE]: assert is not defined] { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:23:3) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19) + at Test.run (node:internal/test_runner/test:673:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + +[Error [ERR_TEST_FAILURE]: this will cause the test to fail] { + failureType: 'testCodeFailure', + cause: Error: this will cause the test to fail + at Immediate.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:30:14) + at process.processImmediate (node:internal/timers:476:21), + code: 'ERR_TEST_FAILURE' +} + + + + + +[Error [ERR_TEST_FAILURE]: callback failure] { + failureType: 'testCodeFailure', + cause: Error: callback failure + at Immediate.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:45:10) + at process.processImmediate (node:internal/timers:476:21), + code: 'ERR_TEST_FAILURE' +} + + + + + +Error [ERR_TEST_FAILURE]: assert is not defined + at async TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:51:3) { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:52:5) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.start (node:internal/test_runner/test:542:17) + at TestContext.test (node:internal/test_runner/test:167:20) + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:51:11) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19), + code: 'ERR_TEST_FAILURE' +} + + + + +Error [ERR_TEST_FAILURE]: assert is not defined + at async TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:55:3) { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:56:5) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.start (node:internal/test_runner/test:542:17) + at TestContext.test (node:internal/test_runner/test:167:20) + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:55:11) + at async Test.run (node:internal/test_runner/test:632:9) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: this does not fail the test] { + failureType: 'testCodeFailure', + cause: Error: this does not fail the test + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:85:9) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19) + at Test.run (node:internal/test_runner/test:673:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: this does not fail the test] { + failureType: 'testCodeFailure', + cause: Error: this does not fail the test + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:99:9) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19) + at Test.run (node:internal/test_runner/test:673:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + +Error [ERR_TEST_FAILURE]: assert is not defined + at async Promise.all (index 0) { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:105:5) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.start (node:internal/test_runner/test:542:17) + at node:internal/test_runner/test:946:71 + at node:internal/per_context/primordials:487:82 + at new Promise (<anonymous>) + at new SafePromise (node:internal/per_context/primordials:455:29) + at node:internal/per_context/primordials:487:9 + at Array.map (<anonymous>), + code: 'ERR_TEST_FAILURE' +} + + + + +[Error [ERR_TEST_FAILURE]: assert is not defined] { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:109:5) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Suite.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19) + at Test.run (node:internal/test_runner/test:673:12) + at async Promise.all (index 0) + at async Suite.run (node:internal/test_runner/test:948:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + +Error [ERR_TEST_FAILURE]: assert is not defined + at async Promise.all (index 0) { + failureType: 'testCodeFailure', + cause: ReferenceError [Error]: assert is not defined + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:114:7) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.start (node:internal/test_runner/test:542:17) + at node:internal/test_runner/test:946:71 + at node:internal/per_context/primordials:487:82 + at new Promise (<anonymous>) + at new SafePromise (node:internal/per_context/primordials:455:29) + at node:internal/per_context/primordials:487:9 + at Array.map (<anonymous>), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: fail] { + failureType: 'testCodeFailure', + cause: Error: fail + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:143:9) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19) + at Test.run (node:internal/test_runner/test:673:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + + + +[Error [ERR_TEST_FAILURE]: fail] { + failureType: 'testCodeFailure', + cause: Error: fail + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:154:11) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Suite.processPendingSubtests (node:internal/test_runner/test:374:18) + at Test.postRun (node:internal/test_runner/test:715:19) + at Test.run (node:internal/test_runner/test:673:12) + at async Promise.all (index 0) + at async Suite.run (node:internal/test_runner/test:948:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + + + + + + + + diff --git a/demo/node-test/package.json b/demo/node-test/package.json new file mode 100644 index 0000000..723707b --- /dev/null +++ b/demo/node-test/package.json @@ -0,0 +1,12 @@ +{ + "name": "test", + "version": "1.0.0", + "main": "index.test.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} From 8bfe0e9435c4a89c8662ac6672f7b4b68a9efef6 Mon Sep 17 00:00:00 2001 From: kbwo Date: Fri, 18 Oct 2024 00:05:59 +0900 Subject: [PATCH 082/139] feat: implement adapter for `node --test` --- crates/adapter/src/model.rs | 6 + crates/adapter/src/runner/mod.rs | 1 + crates/adapter/src/runner/node_test.rs | 847 +++++++++++++++++++++++++ crates/adapter/src/runner/phpunit.rs | 36 +- crates/adapter/src/runner/util.rs | 31 + demo/.vim/coc-settings.json | 11 +- demo/node-test/index.test.js | 6 + demo/node-test/output.xml | 270 +++----- demo/node-test/util.js | 5 + 9 files changed, 1005 insertions(+), 208 deletions(-) create mode 100644 crates/adapter/src/runner/node_test.rs create mode 100644 demo/node-test/util.js diff --git a/crates/adapter/src/model.rs b/crates/adapter/src/model.rs index 44d987e..2eae69c 100644 --- a/crates/adapter/src/model.rs +++ b/crates/adapter/src/model.rs @@ -2,6 +2,7 @@ use crate::runner::cargo_nextest::CargoNextestRunner; use crate::runner::cargo_test::CargoTestRunner; use crate::runner::deno::DenoRunner; use crate::runner::go::GoTestRunner; +use crate::runner::node_test::NodeTestRunner; use crate::runner::phpunit::PhpunitRunner; use crate::runner::vitest::VitestRunner; use std::str::FromStr; @@ -21,6 +22,7 @@ pub enum AvailableTestKind { Deno(DenoRunner), GoTest(GoTestRunner), Phpunit(PhpunitRunner), + NodeTest(NodeTestRunner), } impl Runner for AvailableTestKind { fn discover(&self, args: DiscoverArgs) -> Result<(), LSError> { @@ -32,6 +34,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::GoTest(runner) => runner.discover(args), AvailableTestKind::Vitest(runner) => runner.discover(args), AvailableTestKind::Phpunit(runner) => runner.discover(args), + AvailableTestKind::NodeTest(runner) => runner.discover(args), } } @@ -44,6 +47,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::GoTest(runner) => runner.run_file_test(args), AvailableTestKind::Vitest(runner) => runner.run_file_test(args), AvailableTestKind::Phpunit(runner) => runner.run_file_test(args), + AvailableTestKind::NodeTest(runner) => runner.run_file_test(args), } } @@ -56,6 +60,7 @@ impl Runner for AvailableTestKind { AvailableTestKind::GoTest(runner) => runner.detect_workspaces(args), AvailableTestKind::Vitest(runner) => runner.detect_workspaces(args), AvailableTestKind::Phpunit(runner) => runner.detect_workspaces(args), + AvailableTestKind::NodeTest(runner) => runner.detect_workspaces(args), } } } @@ -72,6 +77,7 @@ impl FromStr for AvailableTestKind { "vitest" => Ok(AvailableTestKind::Vitest(VitestRunner)), "deno" => Ok(AvailableTestKind::Deno(DenoRunner)), "phpunit" => Ok(AvailableTestKind::Phpunit(PhpunitRunner)), + "node-test" => Ok(AvailableTestKind::NodeTest(NodeTestRunner)), _ => Err(anyhow::anyhow!("Unknown test kind: {}", s)), } } diff --git a/crates/adapter/src/runner/mod.rs b/crates/adapter/src/runner/mod.rs index 996bd5e..c7f1066 100644 --- a/crates/adapter/src/runner/mod.rs +++ b/crates/adapter/src/runner/mod.rs @@ -1,5 +1,6 @@ pub mod cargo_nextest; pub mod cargo_test; +pub mod node_test; pub mod deno; pub mod go; pub mod jest; diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs new file mode 100644 index 0000000..923bc4a --- /dev/null +++ b/crates/adapter/src/runner/node_test.rs @@ -0,0 +1,847 @@ +use std::process::Output; + +use regex::Regex; +use testing_language_server::{ + error::LSError, + spec::{ + DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, RunFileTestResult, + RunFileTestResultItem, TestItem, + }, +}; +use xml::{reader::XmlEvent, ParserConfig}; + +use crate::model::Runner; + +use super::util::{ + detect_workspaces_from_file_list, discover_with_treesitter, send_stdout, write_result_log, + ResultFromXml, +}; + +#[derive(Eq, PartialEq, Debug)] +pub struct NodeTestRunner; + +fn discover(file_path: &str) -> Result, LSError> { + // from https://github.com/nvim-neotest/neotest-jest/blob/514fd4eae7da15fd409133086bb8e029b65ac43f/lua/neotest-jest/init.lua#L162 + // license: https://github.com/nvim-neotest/neotest-jest/blob/514fd4eae7da15fd409133086bb8e029b65ac43f/LICENSE.md + let query = r#" + ; -- Namespaces -- + ; Matches: `describe("A thing", () => {})` + ((call_expression + function: (identifier) @func_name (#eq? @func_name "describe") + arguments: (arguments (string (string_fragment) @namespace.name) (arrow_function)) + )) @namespace.definition + ; Matches: `describe("A thing", function() {})` + ((call_expression + function: (identifier) @func_name (#eq? @func_name "describe") + arguments: (arguments (string (string_fragment) @namespace.name) (function_expression)) + )) @namespace.definition + ; Matches: `describe.only("A thing", () => {})` + ((call_expression + function: (member_expression + object: (identifier) @func_name (#eq? @func_name "describe") + property: (property_identifier) @only_property (#eq? @only_property "only") + ) + arguments: (arguments (string (string_fragment) @namespace.name) (arrow_function)) + )) @namespace.definition + ; Matches: `describe.only("A thing", function() {})` + ((call_expression + function: (member_expression + object: (identifier) @func_name (#eq? @func_name "describe") + property: (property_identifier) @only_property (#eq? @only_property "only") + ) + arguments: (arguments (string (string_fragment) @namespace.name) (function_expression)) + )) @namespace.definition + + ; -- Tests -- + ; Matches: `test("test name", (t) => {})` or `it("test name", (t) => {})` + ((call_expression + function: (identifier) @func_name (#any-of? @func_name "test" "it") + arguments: (arguments (string (string_fragment) @test.name) [(arrow_function) (function_expression)]) + )) @test.definition + ; Matches: `test("test name", { skip: true }, (t) => {})` + ((call_expression + function: (identifier) @func_name (#any-of? @func_name "test" "it") + arguments: (arguments + (string (string_fragment) @test.name) + (object) + [(arrow_function) (function_expression)] + ) + )) @test.definition + ; Matches: `test("test name", async (t) => {})` + ((call_expression + function: (identifier) @func_name (#any-of? @func_name "test" "it") + arguments: (arguments + (string (string_fragment) @test.name) + (arrow_function (identifier) @async (#eq? @async "async")) + ) + )) @test.definition + ; Matches: `test("test name", (t, done) => {})` + ((call_expression + function: (identifier) @func_name (#any-of? @func_name "test" "it") + arguments: (arguments + (string (string_fragment) @test.name) + [(arrow_function (formal_parameters (identifier) (identifier))) (function_expression)] + ) + )) @test.definition + + "#; + discover_with_treesitter(file_path, &tree_sitter_javascript::language(), query) +} + +// characters can be like +// \n[Error [ERR_TEST_FAILURE]: assert is not defined] {\n failureType: 'testCodeFailure',\n cause: ReferenceError [Error]: assert is not defined\n at TestContext. (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:6:3)\n at Test.runInAsyncScope (node:async_hooks:203:9)\n at Test.run (node:internal/test_runner/test:631:25)\n at Test.start (node:internal/test_runner/test:542:17)\n at startSubtest (node:internal/test_runner/harness:214:17),\n code: 'ERR_TEST_FAILURE'\n}\n\t\t +fn get_result_from_characters( + error_text: &str, + target_file_paths: &[String], +) -> Result { + let re_path_line = Regex::new(r"\(([^:]+):(\d+):(\d+)\)").unwrap(); + for line in error_text.lines() { + if let Some(caps) = re_path_line.captures(line) { + let file_path = &caps[1]; + if !target_file_paths.contains(&file_path.to_string()) { + continue; + } + return Ok(ResultFromXml { + message: error_text.to_string(), + path: file_path.to_string(), + line: caps[2].parse::().unwrap(), + col: caps[3].parse::().unwrap(), + }); + } + } + + Err(anyhow::anyhow!("Failed to parse error from {}", error_text)) +} + +fn get_result_from_xml( + output: &str, + target_file_paths: &[String], +) -> Result, anyhow::Error> { + use xml::common::Position; + + let mut reader = ParserConfig::default() + .ignore_root_level_whitespace(false) + .create_reader(output.as_bytes()); + + let local_name = "failure"; + + let mut in_failure = false; + let mut result: Vec = Vec::new(); + loop { + match reader.next() { + Ok(e) => match e { + XmlEvent::StartElement { name, .. } => { + if name.local_name.starts_with(local_name) { + in_failure = true; + } + } + XmlEvent::EndElement { .. } => { + in_failure = false; + } + XmlEvent::Characters(data) => { + if let Ok(result_from_xml) = + get_result_from_characters(&data, target_file_paths) + { + if in_failure { + result.push(result_from_xml); + } + } + } + XmlEvent::EndDocument => break, + _ => {} + }, + Err(e) => { + tracing::error!("Error at {}: {e}", reader.position()); + break; + } + } + } + + Ok(result) +} + +impl Runner for NodeTestRunner { + #[tracing::instrument(skip(self))] + fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { + let file_paths = args.file_paths; + let mut discover_results: DiscoverResult = vec![]; + for file_path in file_paths { + discover_results.push(DiscoverResultItem { + tests: discover(&file_path)?, + path: file_path, + }) + } + send_stdout(&discover_results)?; + Ok(()) + } + + #[tracing::instrument(skip(self))] + fn run_file_test( + &self, + args: testing_language_server::spec::RunFileTestArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let workspace_root = args.workspace; + let output = std::process::Command::new("node") + .current_dir(&workspace_root) + .args(["--test", "--test-reporter", "junit"]) + .args(args.extra) + .args(&file_paths) + .output() + .unwrap(); + write_result_log("node-test.xml", &output)?; + let Output { stdout, stderr, .. } = output; + if stdout.is_empty() && !stderr.is_empty() { + return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); + } + let stdout = String::from_utf8(stdout).unwrap(); + let result_from_xml = get_result_from_xml(&stdout, &file_paths)?; + let diagnostics: RunFileTestResult = result_from_xml + .into_iter() + .map(|result_from_xml| { + let result_item: RunFileTestResultItem = result_from_xml.into(); + result_item + }) + .collect(); + send_stdout(&diagnostics)?; + Ok(()) + } + + #[tracing::instrument(skip(self))] + fn detect_workspaces( + &self, + args: testing_language_server::spec::DetectWorkspaceArgs, + ) -> Result<(), LSError> { + let file_paths = args.file_paths; + let detect_result: DetectWorkspaceResult = + detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]); + send_stdout(&detect_result)?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use lsp_types::{Position, Range}; + + use super::*; + + #[test] + fn parse_xml() { + let mut xml_path = std::env::current_dir().unwrap(); + xml_path.push("../../demo/node-test/output.xml"); + let content = std::fs::read_to_string(&xml_path).unwrap(); + let target_file_path = + "/home/test-user/projects/testing-language-server/demo/node-test/index.test.js"; + let result = get_result_from_xml(&content, &[target_file_path.to_string()]).unwrap(); + assert_eq!(result.len(), 9); + + let paths = result + .iter() + .map(|result_from_xml| result_from_xml.path.clone()) + .collect::>(); + for path in paths { + assert_eq!(target_file_path, path.as_str()); + } + + let lines = result + .iter() + .map(|result_from_xml| result_from_xml.line) + .collect::>(); + assert_eq!(lines, [13, 25, 32, 47, 87, 101, 145, 156, 172]); + + let cols = result + .iter() + .map(|result_from_xml| result_from_xml.col) + .collect::>(); + assert_eq!(cols, [10, 10, 14, 10, 9, 9, 9, 11, 3]); + } + + #[test] + fn test_discover() { + let file_path = "../../demo/node-test/index.test.js"; + let test_items = discover(file_path).unwrap(); + assert_eq!(test_items.len(), 24); + assert_eq!( + test_items, + [ + TestItem { + id: "synchronous passing test".to_string(), + name: "synchronous passing test".to_string(), + start_position: Range { + start: Position { + line: 5, + character: 0 + }, + end: Position { + line: 5, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 8, + character: 0 + }, + end: Position { + line: 8, + character: 2 + } + } + }, + TestItem { + id: "synchronous failing test".to_string(), + name: "synchronous failing test".to_string(), + start_position: Range { + start: Position { + line: 10, + character: 0 + }, + end: Position { + line: 10, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 13, + character: 0 + }, + end: Position { + line: 13, + character: 2 + } + } + }, + TestItem { + id: "asynchronous passing test".to_string(), + name: "asynchronous passing test".to_string(), + start_position: Range { + start: Position { + line: 15, + character: 0 + }, + end: Position { + line: 15, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 19, + character: 0 + }, + end: Position { + line: 19, + character: 2 + } + } + }, + TestItem { + id: "asynchronous failing test".to_string(), + name: "asynchronous failing test".to_string(), + start_position: Range { + start: Position { + line: 21, + character: 0 + }, + end: Position { + line: 21, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 25, + character: 0 + }, + end: Position { + line: 25, + character: 2 + } + } + }, + TestItem { + id: "failing test using Promises".to_string(), + name: "failing test using Promises".to_string(), + start_position: Range { + start: Position { + line: 27, + character: 0 + }, + end: Position { + line: 27, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 34, + character: 0 + }, + end: Position { + line: 34, + character: 2 + } + } + }, + TestItem { + id: "callback passing test".to_string(), + name: "callback passing test".to_string(), + start_position: Range { + start: Position { + line: 36, + character: 0 + }, + end: Position { + line: 36, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 40, + character: 0 + }, + end: Position { + line: 40, + character: 2 + } + } + }, + TestItem { + id: "callback failing test".to_string(), + name: "callback failing test".to_string(), + start_position: Range { + start: Position { + line: 42, + character: 0 + }, + end: Position { + line: 42, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 48, + character: 0 + }, + end: Position { + line: 48, + character: 2 + } + } + }, + TestItem { + id: "top level test".to_string(), + name: "top level test".to_string(), + start_position: Range { + start: Position { + line: 51, + character: 0 + }, + end: Position { + line: 51, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 59, + character: 0 + }, + end: Position { + line: 59, + character: 2 + } + } + }, + TestItem { + id: "skip option".to_string(), + name: "skip option".to_string(), + start_position: Range { + start: Position { + line: 63, + character: 0 + }, + end: Position { + line: 63, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 65, + character: 0 + }, + end: Position { + line: 65, + character: 2 + } + } + }, + TestItem { + id: "skip option with message".to_string(), + name: "skip option with message".to_string(), + start_position: Range { + start: Position { + line: 68, + character: 0 + }, + end: Position { + line: 68, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 70, + character: 0 + }, + end: Position { + line: 70, + character: 2 + } + } + }, + TestItem { + id: "skip() method".to_string(), + name: "skip() method".to_string(), + start_position: Range { + start: Position { + line: 72, + character: 0 + }, + end: Position { + line: 72, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 75, + character: 0 + }, + end: Position { + line: 75, + character: 2 + } + } + }, + TestItem { + id: "skip() method with message".to_string(), + name: "skip() method with message".to_string(), + start_position: Range { + start: Position { + line: 77, + character: 0 + }, + end: Position { + line: 77, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 80, + character: 0 + }, + end: Position { + line: 80, + character: 2 + } + } + }, + TestItem { + id: "todo option".to_string(), + name: "todo option".to_string(), + start_position: Range { + start: Position { + line: 84, + character: 0 + }, + end: Position { + line: 84, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 87, + character: 0 + }, + end: Position { + line: 87, + character: 2 + } + } + }, + TestItem { + id: "todo option with message".to_string(), + name: "todo option with message".to_string(), + start_position: Range { + start: Position { + line: 90, + character: 0 + }, + end: Position { + line: 90, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 92, + character: 0 + }, + end: Position { + line: 92, + character: 2 + } + } + }, + TestItem { + id: "todo() method".to_string(), + name: "todo() method".to_string(), + start_position: Range { + start: Position { + line: 94, + character: 0 + }, + end: Position { + line: 94, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 96, + character: 0 + }, + end: Position { + line: 96, + character: 2 + } + } + }, + TestItem { + id: "todo() method with message".to_string(), + name: "todo() method with message".to_string(), + start_position: Range { + start: Position { + line: 98, + character: 0 + }, + end: Position { + line: 98, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 101, + character: 0 + }, + end: Position { + line: 101, + character: 2 + } + } + }, + TestItem { + id: "A thing::should work".to_string(), + name: "A thing::should work".to_string(), + start_position: Range { + start: Position { + line: 105, + character: 2 + }, + end: Position { + line: 105, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 107, + character: 0 + }, + end: Position { + line: 107, + character: 4 + } + } + }, + TestItem { + id: "A thing::should be ok".to_string(), + name: "A thing::should be ok".to_string(), + start_position: Range { + start: Position { + line: 109, + character: 2 + }, + end: Position { + line: 109, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 111, + character: 0 + }, + end: Position { + line: 111, + character: 4 + } + } + }, + TestItem { + id: "a nested thing::should work".to_string(), + name: "a nested thing::should work".to_string(), + start_position: Range { + start: Position { + line: 114, + character: 4 + }, + end: Position { + line: 114, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 116, + character: 0 + }, + end: Position { + line: 116, + character: 6 + } + } + }, + TestItem { + id: "a nested thing::this test is run".to_string(), + name: "a nested thing::this test is run".to_string(), + start_position: Range { + start: Position { + line: 123, + character: 0 + }, + end: Position { + line: 123, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 139, + character: 0 + }, + end: Position { + line: 139, + character: 2 + } + } + }, + TestItem { + id: "a nested thing::this test is not run".to_string(), + name: "a nested thing::this test is not run".to_string(), + start_position: Range { + start: Position { + line: 142, + character: 0 + }, + end: Position { + line: 142, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 145, + character: 0 + }, + end: Position { + line: 145, + character: 2 + } + } + }, + TestItem { + id: "a suite::this test is run".to_string(), + name: "a suite::this test is run".to_string(), + start_position: Range { + start: Position { + line: 149, + character: 2 + }, + end: Position { + line: 149, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 151, + character: 0 + }, + end: Position { + line: 151, + character: 4 + } + } + }, + TestItem { + id: "a suite::this test is not run".to_string(), + name: "a suite::this test is not run".to_string(), + start_position: Range { + start: Position { + line: 153, + character: 2 + }, + end: Position { + line: 153, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 156, + character: 0 + }, + end: Position { + line: 156, + character: 4 + } + } + }, + TestItem { + id: "a suite::must be fail".to_string(), + name: "a suite::must be fail".to_string(), + start_position: Range { + start: Position { + line: 170, + character: 0 + }, + end: Position { + line: 170, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 172, + character: 0 + }, + end: Position { + line: 172, + character: 2 + } + } + } + ] + ); + } +} diff --git a/crates/adapter/src/runner/phpunit.rs b/crates/adapter/src/runner/phpunit.rs index c54dc7b..0d765d8 100644 --- a/crates/adapter/src/runner/phpunit.rs +++ b/crates/adapter/src/runner/phpunit.rs @@ -1,4 +1,3 @@ -use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; use std::fs::File; use std::io::BufReader; use std::process::Output; @@ -12,40 +11,10 @@ use xml::reader::{ParserConfig, XmlEvent}; use crate::model::Runner; use super::util::{ - detect_workspaces_from_file_list, discover_with_treesitter, send_stdout, LOG_LOCATION, - MAX_CHAR_LENGTH, + detect_workspaces_from_file_list, discover_with_treesitter, send_stdout, ResultFromXml, + LOG_LOCATION, }; -#[derive(Debug)] -pub struct ResultFromXml { - pub message: String, - pub path: String, - pub line: u32, -} - -impl Into for ResultFromXml { - fn into(self) -> RunFileTestResultItem { - RunFileTestResultItem { - path: self.path, - diagnostics: vec![Diagnostic { - message: self.message, - range: Range { - start: Position { - line: self.line - 1, - character: 0, - }, - end: Position { - line: self.line - 1, - character: MAX_CHAR_LENGTH, - }, - }, - severity: Some(DiagnosticSeverity::ERROR), - ..Default::default() - }], - } - } -} - fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { detect_workspaces_from_file_list(&file_paths, &["composer.json".to_string()]) } @@ -69,6 +38,7 @@ fn get_result_from_characters(characters: &str) -> Result = LazyLock::new(|| { // If the character value is greater than the line length it defaults back to the line length. pub const MAX_CHAR_LENGTH: u32 = 10000; +#[derive(Debug)] +pub struct ResultFromXml { + pub message: String, + pub path: String, + pub line: u32, + pub col: u32, +} + +impl Into for ResultFromXml { + fn into(self) -> RunFileTestResultItem { + RunFileTestResultItem { + path: self.path, + diagnostics: vec![Diagnostic { + message: self.message, + range: Range { + start: Position { + line: self.line - 1, + character: self.col - 1, + }, + end: Position { + line: self.line - 1, + character: MAX_CHAR_LENGTH, + }, + }, + severity: Some(DiagnosticSeverity::ERROR), + ..Default::default() + }], + } + } +} + /// determine if a particular file is the root of workspace based on whether it is in the same directory fn detect_workspace_from_file(file_path: PathBuf, file_names: &[String]) -> Option { let parent = file_path.parent(); diff --git a/demo/.vim/coc-settings.json b/demo/.vim/coc-settings.json index 8558366..79ac54b 100644 --- a/demo/.vim/coc-settings.json +++ b/demo/.vim/coc-settings.json @@ -54,6 +54,14 @@ "exclude": [] } ], + "node-test": [ + { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=node-test"], + "include": ["/node-test/*.test.js"], + "exclude": [] + } + ], "phpunit": [ { "path": "testing-ls-adapter", @@ -66,5 +74,6 @@ } } }, - "deno.enable": true + "deno.enable": false, + "tsserver.enable": false } diff --git a/demo/node-test/index.test.js b/demo/node-test/index.test.js index 54013b2..6d84a99 100644 --- a/demo/node-test/index.test.js +++ b/demo/node-test/index.test.js @@ -1,5 +1,7 @@ const test = require("node:test"); const { describe, it } = require("node:test"); +const assert = require("node:assert"); +const { throwError } = require("./util.js"); // # Basic example test("synchronous passing test", (t) => { // This test passes because it does not throw an exception. @@ -165,3 +167,7 @@ describe.only("a suite", () => { // This code is run. }); }); + +test("import from external file. this must be fail", () => { + throwError(); +}); diff --git a/demo/node-test/output.xml b/demo/node-test/output.xml index 6e342ed..1e05ac7 100644 --- a/demo/node-test/output.xml +++ b/demo/node-test/output.xml @@ -1,149 +1,109 @@ - - -[Error [ERR_TEST_FAILURE]: assert is not defined] { + + + +[Error [ERR_TEST_FAILURE]: Expected values to be strictly equal: + +1 !== 2 +] { failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:6:3) - at Test.runInAsyncScope (node:async_hooks:203:9) - at Test.run (node:internal/test_runner/test:631:25) - at Test.start (node:internal/test_runner/test:542:17) - at startSubtest (node:internal/test_runner/harness:214:17), - code: 'ERR_TEST_FAILURE' -} - - - - -[Error [ERR_TEST_FAILURE]: assert is not defined] { - failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:11:3) + cause: AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 1 !== 2 + + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:13:10) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:631:25) at Test.processPendingSubtests (node:internal/test_runner/test:374:18) at Test.postRun (node:internal/test_runner/test:715:19) at Test.run (node:internal/test_runner/test:673:12) - at async startSubtest (node:internal/test_runner/harness:214:3), + at async startSubtest (node:internal/test_runner/harness:214:3) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 1, + expected: 2, + operator: 'strictEqual' + }, code: 'ERR_TEST_FAILURE' } - - -[Error [ERR_TEST_FAILURE]: assert is not defined] { + + + +[Error [ERR_TEST_FAILURE]: Expected values to be strictly equal: + +1 !== 2 +] { failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:17:3) + cause: AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 1 !== 2 + + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:25:10) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:631:25) at Test.processPendingSubtests (node:internal/test_runner/test:374:18) at Test.postRun (node:internal/test_runner/test:715:19) at Test.run (node:internal/test_runner/test:673:12) - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 1, + expected: 2, + operator: 'strictEqual' + }, code: 'ERR_TEST_FAILURE' } - - -[Error [ERR_TEST_FAILURE]: assert is not defined] { - failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:23:3) - at Test.runInAsyncScope (node:async_hooks:203:9) - at Test.run (node:internal/test_runner/test:631:25) - at Test.processPendingSubtests (node:internal/test_runner/test:374:18) - at Test.postRun (node:internal/test_runner/test:715:19) - at Test.run (node:internal/test_runner/test:673:12) - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' -} - - - + [Error [ERR_TEST_FAILURE]: this will cause the test to fail] { failureType: 'testCodeFailure', cause: Error: this will cause the test to fail - at Immediate.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:30:14) + at Immediate.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:32:14) at process.processImmediate (node:internal/timers:476:21), code: 'ERR_TEST_FAILURE' } - - + + [Error [ERR_TEST_FAILURE]: callback failure] { failureType: 'testCodeFailure', cause: Error: callback failure - at Immediate.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:45:10) + at Immediate.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:47:10) at process.processImmediate (node:internal/timers:476:21), code: 'ERR_TEST_FAILURE' } - - - -Error [ERR_TEST_FAILURE]: assert is not defined - at async TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:51:3) { - failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:52:5) - at Test.runInAsyncScope (node:async_hooks:203:9) - at Test.run (node:internal/test_runner/test:631:25) - at Test.start (node:internal/test_runner/test:542:17) - at TestContext.test (node:internal/test_runner/test:167:20) - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:51:11) - at Test.runInAsyncScope (node:async_hooks:203:9) - at Test.run (node:internal/test_runner/test:631:25) - at Test.processPendingSubtests (node:internal/test_runner/test:374:18) - at Test.postRun (node:internal/test_runner/test:715:19), - code: 'ERR_TEST_FAILURE' -} - - - - -Error [ERR_TEST_FAILURE]: assert is not defined - at async TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:55:3) { - failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:56:5) - at Test.runInAsyncScope (node:async_hooks:203:9) - at Test.run (node:internal/test_runner/test:631:25) - at Test.start (node:internal/test_runner/test:542:17) - at TestContext.test (node:internal/test_runner/test:167:20) - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:55:11) - at async Test.run (node:internal/test_runner/test:632:9) - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' -} - - + + + - + - + - + - + [Error [ERR_TEST_FAILURE]: this does not fail the test] { failureType: 'testCodeFailure', cause: Error: this does not fail the test - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:85:9) + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:87:9) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:631:25) at Test.processPendingSubtests (node:internal/test_runner/test:374:18) @@ -154,19 +114,19 @@ Error [ERR_TEST_FAILURE]: assert is not defined } - + - + - + [Error [ERR_TEST_FAILURE]: this does not fail the test] { failureType: 'testCodeFailure', cause: Error: this does not fail the test - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:99:9) + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:101:9) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:631:25) at Test.processPendingSubtests (node:internal/test_runner/test:374:18) @@ -177,88 +137,33 @@ Error [ERR_TEST_FAILURE]: assert is not defined } - - - -Error [ERR_TEST_FAILURE]: assert is not defined - at async Promise.all (index 0) { - failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:105:5) - at Test.runInAsyncScope (node:async_hooks:203:9) - at Test.run (node:internal/test_runner/test:631:25) - at Test.start (node:internal/test_runner/test:542:17) - at node:internal/test_runner/test:946:71 - at node:internal/per_context/primordials:487:82 - at new Promise (<anonymous>) - at new SafePromise (node:internal/per_context/primordials:455:29) - at node:internal/per_context/primordials:487:9 - at Array.map (<anonymous>), - code: 'ERR_TEST_FAILURE' -} - - - - -[Error [ERR_TEST_FAILURE]: assert is not defined] { - failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:109:5) - at Test.runInAsyncScope (node:async_hooks:203:9) - at Test.run (node:internal/test_runner/test:631:25) - at Suite.processPendingSubtests (node:internal/test_runner/test:374:18) - at Test.postRun (node:internal/test_runner/test:715:19) - at Test.run (node:internal/test_runner/test:673:12) - at async Promise.all (index 0) - at async Suite.run (node:internal/test_runner/test:948:7) - at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), - code: 'ERR_TEST_FAILURE' -} - - - - - -Error [ERR_TEST_FAILURE]: assert is not defined - at async Promise.all (index 0) { - failureType: 'testCodeFailure', - cause: ReferenceError [Error]: assert is not defined - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:114:7) - at Test.runInAsyncScope (node:async_hooks:203:9) - at Test.run (node:internal/test_runner/test:631:25) - at Test.start (node:internal/test_runner/test:542:17) - at node:internal/test_runner/test:946:71 - at node:internal/per_context/primordials:487:82 - at new Promise (<anonymous>) - at new SafePromise (node:internal/per_context/primordials:455:29) - at node:internal/per_context/primordials:487:9 - at Array.map (<anonymous>), - code: 'ERR_TEST_FAILURE' -} - - + + + + + - - - + + + - + - - + + - + - + [Error [ERR_TEST_FAILURE]: fail] { failureType: 'testCodeFailure', cause: Error: fail - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:143:9) + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:145:9) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:631:25) at Test.processPendingSubtests (node:internal/test_runner/test:374:18) @@ -269,15 +174,15 @@ Error [ERR_TEST_FAILURE]: assert is not defined } - - + + - + [Error [ERR_TEST_FAILURE]: fail] { failureType: 'testCodeFailure', cause: Error: fail - at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:154:11) + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:156:11) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:631:25) at Suite.processPendingSubtests (node:internal/test_runner/test:374:18) @@ -291,17 +196,34 @@ Error [ERR_TEST_FAILURE]: assert is not defined - + - + - + + +[Error [ERR_TEST_FAILURE]: this will cause the test to fail] { + failureType: 'testCodeFailure', + cause: Error: this will cause the test to fail + at throwError (/home/test-user/projects/testing-language-server/demo/node-test/util.js:2:9) + at TestContext.<anonymous> (/home/test-user/projects/testing-language-server/demo/node-test/index.test.js:172:3) + at Test.runInAsyncScope (node:async_hooks:203:9) + at Test.run (node:internal/test_runner/test:631:25) + at Test.processPendingSubtests (node:internal/test_runner/test:374:18) + at Suite.postRun (node:internal/test_runner/test:715:19) + at Suite.run (node:internal/test_runner/test:962:10) + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + - - + + - + diff --git a/demo/node-test/util.js b/demo/node-test/util.js new file mode 100644 index 0000000..3c75c35 --- /dev/null +++ b/demo/node-test/util.js @@ -0,0 +1,5 @@ +const throwError = () => { + throw new Error("this will cause the test to fail"); +}; + +module.exports = { throwError }; From 7ce2e97df67f1b90b36a80126eefb4f23ba1275c Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 19 Oct 2024 13:41:09 +0900 Subject: [PATCH 083/139] fix(adapter): fix top level tests to not be in namespace --- crates/adapter/src/runner/node_test.rs | 112 ++++++++++++++++++++----- crates/adapter/src/runner/util.rs | 1 + demo/jest/another.spec.js | 4 + demo/node-test/index.test.js | 12 +-- 4 files changed, 102 insertions(+), 27 deletions(-) diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs index 923bc4a..79b128b 100644 --- a/crates/adapter/src/runner/node_test.rs +++ b/crates/adapter/src/runner/node_test.rs @@ -25,29 +25,27 @@ fn discover(file_path: &str) -> Result, LSError> { // license: https://github.com/nvim-neotest/neotest-jest/blob/514fd4eae7da15fd409133086bb8e029b65ac43f/LICENSE.md let query = r#" ; -- Namespaces -- - ; Matches: `describe("A thing", () => {})` + ; Matches: `describe('context', () => {})` ((call_expression function: (identifier) @func_name (#eq? @func_name "describe") arguments: (arguments (string (string_fragment) @namespace.name) (arrow_function)) )) @namespace.definition - ; Matches: `describe("A thing", function() {})` + ; Matches: `describe('context', function() {})` ((call_expression function: (identifier) @func_name (#eq? @func_name "describe") arguments: (arguments (string (string_fragment) @namespace.name) (function_expression)) )) @namespace.definition - ; Matches: `describe.only("A thing", () => {})` + ; Matches: `describe.only('context', () => {})` ((call_expression function: (member_expression - object: (identifier) @func_name (#eq? @func_name "describe") - property: (property_identifier) @only_property (#eq? @only_property "only") + object: (identifier) @func_name (#any-of? @func_name "describe") ) arguments: (arguments (string (string_fragment) @namespace.name) (arrow_function)) )) @namespace.definition - ; Matches: `describe.only("A thing", function() {})` + ; Matches: `describe.only('context', function() {})` ((call_expression function: (member_expression - object: (identifier) @func_name (#eq? @func_name "describe") - property: (property_identifier) @only_property (#eq? @only_property "only") + object: (identifier) @func_name (#any-of? @func_name "describe") ) arguments: (arguments (string (string_fragment) @namespace.name) (function_expression)) )) @namespace.definition @@ -261,7 +259,7 @@ mod tests { fn test_discover() { let file_path = "../../demo/node-test/index.test.js"; let test_items = discover(file_path).unwrap(); - assert_eq!(test_items.len(), 24); + assert_eq!(test_items.len(), 27); assert_eq!( test_items, [ @@ -674,8 +672,8 @@ mod tests { } }, TestItem { - id: "A thing::should be ok".to_string(), - name: "A thing::should be ok".to_string(), + id: "should be ok".to_string(), + name: "should be ok".to_string(), start_position: Range { start: Position { line: 109, @@ -722,8 +720,8 @@ mod tests { } }, TestItem { - id: "a nested thing::this test is run".to_string(), - name: "a nested thing::this test is run".to_string(), + id: "this test is run".to_string(), + name: "this test is run".to_string(), start_position: Range { start: Position { line: 123, @@ -746,8 +744,8 @@ mod tests { } }, TestItem { - id: "a nested thing::this test is not run".to_string(), - name: "a nested thing::this test is not run".to_string(), + id: "this test is not run".to_string(), + name: "this test is not run".to_string(), start_position: Range { start: Position { line: 142, @@ -770,8 +768,8 @@ mod tests { } }, TestItem { - id: "a suite::this test is run".to_string(), - name: "a suite::this test is run".to_string(), + id: "A suite::this test is run A ".to_string(), + name: "A suite::this test is run A ".to_string(), start_position: Range { start: Position { line: 149, @@ -794,8 +792,32 @@ mod tests { } }, TestItem { - id: "a suite::this test is not run".to_string(), - name: "a suite::this test is not run".to_string(), + id: "this test is run A ".to_string(), + name: "this test is run A ".to_string(), + start_position: Range { + start: Position { + line: 149, + character: 2 + }, + end: Position { + line: 149, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 151, + character: 0 + }, + end: Position { + line: 151, + character: 4 + } + } + }, + TestItem { + id: "this test is not run B".to_string(), + name: "this test is not run B".to_string(), start_position: Range { start: Position { line: 153, @@ -818,8 +840,56 @@ mod tests { } }, TestItem { - id: "a suite::must be fail".to_string(), - name: "a suite::must be fail".to_string(), + id: "B suite::this test is run A".to_string(), + name: "B suite::this test is run A".to_string(), + start_position: Range { + start: Position { + line: 161, + character: 2 + }, + end: Position { + line: 161, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 163, + character: 0 + }, + end: Position { + line: 163, + character: 4 + } + } + }, + TestItem { + id: "this test is run B".to_string(), + name: "this test is run B".to_string(), + start_position: Range { + start: Position { + line: 165, + character: 2 + }, + end: Position { + line: 165, + character: 10000 + } + }, + end_position: Range { + start: Position { + line: 167, + character: 0 + }, + end: Position { + line: 167, + character: 4 + } + } + }, + TestItem { + id: "import from external file. this must be fail".to_string(), + name: "import from external file. this must be fail".to_string(), start_position: Range { start: Position { line: 170, diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index c7f4fe5..f5468a5 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -234,6 +234,7 @@ pub fn discover_with_treesitter( test_items.push(test_item); test_start_position = Point::default(); test_end_position = Point::default(); + namespace = ""; } _ => {} } diff --git a/demo/jest/another.spec.js b/demo/jest/another.spec.js index f2ad3c0..a3eb7d8 100644 --- a/demo/jest/another.spec.js +++ b/demo/jest/another.spec.js @@ -7,3 +7,7 @@ describe("another", () => { expect(1).toBe(1); }); }); + +test("toplevel test", () => { + expect(1).toBe(2); +}); diff --git a/demo/node-test/index.test.js b/demo/node-test/index.test.js index 6d84a99..5ef1f10 100644 --- a/demo/node-test/index.test.js +++ b/demo/node-test/index.test.js @@ -145,25 +145,25 @@ test("this test is not run", () => { throw new Error("fail"); }); -describe("a suite", () => { +describe("A suite", () => { // The 'only' option is set, so this test is run. - it("this test is run", { only: true }, () => { + it("this test is run A ", { only: true }, () => { // This code is run. }); - it("this test is not run", () => { + it("this test is not run B", () => { // This code is not run. throw new Error("fail"); }); }); -describe.only("a suite", () => { +describe.only("B suite", () => { // The 'only' option is set, so this test is run. - it("this test is run", () => { + it("this test is run A", () => { // This code is run. }); - it("this test is run", () => { + it("this test is run B", () => { // This code is run. }); }); From cf926f56a23d34eae5fd5c757883e50571cef7e7 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 19 Oct 2024 16:50:11 +0900 Subject: [PATCH 084/139] fix(adapter): support nested namespace definition --- crates/adapter/src/runner/node_test.rs | 54 +++++++------------------- crates/adapter/src/runner/util.rs | 38 +++++++++++++++--- crates/adapter/src/runner/vitest.rs | 2 +- demo/node-test/index.test.js | 8 ++-- 4 files changed, 53 insertions(+), 49 deletions(-) diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs index 79b128b..117ad61 100644 --- a/crates/adapter/src/runner/node_test.rs +++ b/crates/adapter/src/runner/node_test.rs @@ -259,7 +259,7 @@ mod tests { fn test_discover() { let file_path = "../../demo/node-test/index.test.js"; let test_items = discover(file_path).unwrap(); - assert_eq!(test_items.len(), 27); + assert_eq!(test_items.len(), 26); assert_eq!( test_items, [ @@ -672,8 +672,8 @@ mod tests { } }, TestItem { - id: "should be ok".to_string(), - name: "should be ok".to_string(), + id: "A thing::should be ok".to_string(), + name: "A thing::should be ok".to_string(), start_position: Range { start: Position { line: 109, @@ -696,8 +696,8 @@ mod tests { } }, TestItem { - id: "a nested thing::should work".to_string(), - name: "a nested thing::should work".to_string(), + id: "A thing::a nested thing::should work".to_string(), + name: "A thing::a nested thing::should work".to_string(), start_position: Range { start: Position { line: 114, @@ -720,8 +720,8 @@ mod tests { } }, TestItem { - id: "this test is run".to_string(), - name: "this test is run".to_string(), + id: "only: this test is run".to_string(), + name: "only: this test is run".to_string(), start_position: Range { start: Position { line: 123, @@ -744,8 +744,8 @@ mod tests { } }, TestItem { - id: "this test is not run".to_string(), - name: "this test is not run".to_string(), + id: "only: this test is not run".to_string(), + name: "only: this test is not run".to_string(), start_position: Range { start: Position { line: 142, @@ -792,32 +792,8 @@ mod tests { } }, TestItem { - id: "this test is run A ".to_string(), - name: "this test is run A ".to_string(), - start_position: Range { - start: Position { - line: 149, - character: 2 - }, - end: Position { - line: 149, - character: 10000 - } - }, - end_position: Range { - start: Position { - line: 151, - character: 0 - }, - end: Position { - line: 151, - character: 4 - } - } - }, - TestItem { - id: "this test is not run B".to_string(), - name: "this test is not run B".to_string(), + id: "A suite::this test is not run B".to_string(), + name: "A suite::this test is not run B".to_string(), start_position: Range { start: Position { line: 153, @@ -840,8 +816,8 @@ mod tests { } }, TestItem { - id: "B suite::this test is run A".to_string(), - name: "B suite::this test is run A".to_string(), + id: "this test is run C".to_string(), + name: "this test is run C".to_string(), start_position: Range { start: Position { line: 161, @@ -864,8 +840,8 @@ mod tests { } }, TestItem { - id: "this test is run B".to_string(), - name: "this test is run B".to_string(), + id: "this test is run D".to_string(), + name: "this test is run D".to_string(), start_position: Range { start: Position { line: 165, diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index f5468a5..b93a7ce 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -12,6 +12,8 @@ use testing_language_server::spec::{RunFileTestResultItem, TestItem}; use testing_language_server::{error::LSError, spec::RunFileTestResult}; use tree_sitter::{Language, Point, Query, QueryCursor}; +pub struct DiscoverWithTSOption {} + pub static LOG_LOCATION: LazyLock = LazyLock::new(|| { let home_dir = dirs::home_dir().unwrap(); home_dir.join(".config/testing_language_server/adapter/") @@ -178,7 +180,9 @@ pub fn discover_with_treesitter( cursor.set_byte_range(tree.root_node().byte_range()); let source = source_code.as_bytes(); let matches = cursor.matches(&query, tree.root_node(), source); - let mut namespace = ""; + + let mut namespace_name = String::new(); + let mut namespace_position_stack: Vec<(Point, Point)> = vec![]; let mut test_id_set = HashSet::new(); for m in matches { let mut test_start_position = Point::default(); @@ -188,25 +192,50 @@ pub fn discover_with_treesitter( let value = capture.node.utf8_text(source)?; let start_position = capture.node.start_position(); let end_position = capture.node.end_position(); + match capture_name { + "namespace.definition" => { + namespace_position_stack.push((start_position, end_position)); + } "namespace.name" => { - namespace = value; + let current_namespace = namespace_position_stack.first(); + if let Some((ns_start, ns_end)) = current_namespace { + // In namespace definition + if start_position.row >= ns_start.row + && end_position.row <= ns_end.row + && !namespace_name.is_empty() + { + namespace_name = format!("{}::{}", namespace_name, value); + } else { + namespace_name = value.to_string(); + } + } else { + namespace_name = value.to_string(); + } } "test.definition" => { + if let Some((ns_start, ns_end)) = namespace_position_stack.first() { + if start_position.row < ns_start.row || end_position.row > ns_end.row { + namespace_position_stack.remove(0); + namespace_name = String::new(); + } + } test_start_position = start_position; test_end_position = end_position; } "test.name" => { - let test_id = if namespace.is_empty() { + let test_id = if namespace_name.is_empty() { value.to_string() } else { - [namespace, value].join("::") + format!("{}::{}", namespace_name, value) }; + if test_id_set.contains(&test_id) { continue; } else { test_id_set.insert(test_id.clone()); } + let test_item = TestItem { id: test_id.clone(), name: test_id, @@ -234,7 +263,6 @@ pub fn discover_with_treesitter( test_items.push(test_item); test_start_position = Point::default(); test_end_position = Point::default(); - namespace = ""; } _ => {} } diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 225b22c..11c18f7 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -208,7 +208,7 @@ mod tests { assert_eq!(test_items.len(), 2); assert_eq!( test_items, - vec![ + [ TestItem { id: "describe text::pass".to_string(), name: "describe text::pass".to_string(), diff --git a/demo/node-test/index.test.js b/demo/node-test/index.test.js index 5ef1f10..1836ed5 100644 --- a/demo/node-test/index.test.js +++ b/demo/node-test/index.test.js @@ -121,7 +121,7 @@ describe("A thing", () => { // # only tests // Assume Node.js is run with the --test-only command-line option. // The suite's 'only' option is set, so these tests are run. -test("this test is run", { only: true }, async (t) => { +test("only: this test is run", { only: true }, async (t) => { // Within this test, all subtests are run by default. await t.test("running subtest"); @@ -140,7 +140,7 @@ test("this test is run", { only: true }, async (t) => { }); // The 'only' option is not set, so this test is skipped. -test("this test is not run", () => { +test("only: this test is not run", () => { // This code is not run. throw new Error("fail"); }); @@ -159,11 +159,11 @@ describe("A suite", () => { describe.only("B suite", () => { // The 'only' option is set, so this test is run. - it("this test is run A", () => { + it("this test is run C", () => { // This code is run. }); - it("this test is run B", () => { + it("this test is run D", () => { // This code is run. }); }); From 48c2388d95f46ce5f18c0d010280252e3cd8506a Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 19 Oct 2024 16:57:56 +0900 Subject: [PATCH 085/139] chore(demo): update vscode settings --- demo/.vscode/settings.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/demo/.vscode/settings.json b/demo/.vscode/settings.json index 3252c69..6e33949 100644 --- a/demo/.vscode/settings.json +++ b/demo/.vscode/settings.json @@ -1,6 +1,6 @@ { "testing.enable": true, - "testing.fileTypes": ["rust"], + "filetypes": ["rust", "javascript", "go", "typescript", "php"], "testing.adapterCommand": { "cargo-nextest": [ { @@ -42,6 +42,14 @@ "exclude": [] } ], + "node-test": [ + { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=node-test"], + "include": ["/node-test/*.test.js"], + "exclude": [] + } + ], "phpunit": [ { "path": "testing-ls-adapter", From 310263bea58e4cb6189f98f04cbf99891853a3b0 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 19 Oct 2024 17:12:33 +0900 Subject: [PATCH 086/139] chore: add logs for troubleshooting --- src/server.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/server.rs b/src/server.rs index c1daa4d..4d045dd 100644 --- a/src/server.rs +++ b/src/server.rs @@ -181,7 +181,15 @@ impl TestingLS { .map_err(|err| LSError::Adapter(err.to_string()))?; let adapter_result = String::from_utf8(output.stdout) .map_err(|err| LSError::Adapter(err.to_string()))?; - let workspace: DetectWorkspaceResult = serde_json::from_str(&adapter_result)?; + let workspace: DetectWorkspaceResult = match serde_json::from_str(&adapter_result) { + Ok(result) => result, + Err(err) => { + let stderr = String::from_utf8(output.stderr); + tracing::error!("Failed to parse adapter result: {:?}", err); + tracing::error!("Error: {:?}", stderr); + return Err(LSError::Adapter(err.to_string())); + } + }; let workspace = if let Some(workspace_dir) = workspace_dir { let workspace_dir = resolve_path(&project_dir, workspace_dir) .to_str() @@ -614,4 +622,4 @@ mod tests { let status = server.diagnose_workspace().unwrap(); assert_eq!(status, WorkspaceDiagnosticsStatus::Skipped); } -} \ No newline at end of file +} From 1fc98e90631a7e7baae4f8caa05a2ff22b177bee Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 19 Oct 2024 17:13:34 +0900 Subject: [PATCH 087/139] chore: update version --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/adapter/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1690510..14ad310 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,7 +717,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.14" +version = "0.0.15" dependencies = [ "anyhow", "chrono", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "testing-ls-adapter" -version = "0.0.8" +version = "0.0.9" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index d1a81bc..e316719 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.14" +version = "0.0.15" edition = "2021" description = "LSP server for testing" license = "MIT" diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 44c0122..cadf73a 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.8" +version = "0.0.9" edition = "2021" description = "testing-language-server adapter" license = "MIT" From ee2acbb3a48b1a65d95cf3a073a499180394fee2 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 19 Oct 2024 17:14:16 +0900 Subject: [PATCH 088/139] docs: update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 12aa099..77ffafe 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ language server config: - [x] `go test` - [x] `phpunit` - [x] `vitest` +- [x] `node --test` (Node Test Runner) ### Writing custom adapter ⚠ The specification of adapter CLI is not stabilized yet. From 6c77af09c966356a0018c912418c5d8fb271079e Mon Sep 17 00:00:00 2001 From: kbwo Date: Fri, 25 Oct 2024 00:40:19 +0900 Subject: [PATCH 089/139] fix: change data structure of initialization params --- src/server.rs | 118 +++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/src/server.rs b/src/server.rs index 4d045dd..c9d6405 100644 --- a/src/server.rs +++ b/src/server.rs @@ -17,7 +17,7 @@ use std::process::Output; #[derive(Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct InitializedOptions { - adapter_command: HashMap>, + adapter_command: HashMap, enable_workspace_diagnostics: Option, } @@ -87,7 +87,7 @@ impl TestingLS { Ok(()) } - fn adapter_commands(&self) -> HashMap> { + fn adapter_commands(&self) -> HashMap { self.options.adapter_command.clone() } @@ -150,62 +150,60 @@ impl TestingLS { let project_dir = self.project_dir()?; self.workspaces_cache = vec![]; // Nested and multiple loops, but each count is small - for adapter_commands in adapter_commands.into_values() { - for adapter in adapter_commands.into_iter() { - let AdapterConfiguration { - path, - extra_arg, - env, - include, - exclude, - workspace_dir, - .. - } = &adapter; - let file_paths = Self::project_files(&project_dir, include, exclude); - if file_paths.is_empty() { - continue; - } - let mut adapter_command = Command::new(path); - let mut args_file_path: Vec<&str> = vec![]; - file_paths.iter().for_each(|file_path| { - args_file_path.push("--file-paths"); - args_file_path.push(file_path); - }); - let output = adapter_command - .arg("detect-workspace") - .args(args_file_path) - .arg("--") - .args(extra_arg) - .envs(env) - .output() - .map_err(|err| LSError::Adapter(err.to_string()))?; - let adapter_result = String::from_utf8(output.stdout) - .map_err(|err| LSError::Adapter(err.to_string()))?; - let workspace: DetectWorkspaceResult = match serde_json::from_str(&adapter_result) { - Ok(result) => result, - Err(err) => { - let stderr = String::from_utf8(output.stderr); - tracing::error!("Failed to parse adapter result: {:?}", err); - tracing::error!("Error: {:?}", stderr); - return Err(LSError::Adapter(err.to_string())); - } - }; - let workspace = if let Some(workspace_dir) = workspace_dir { - let workspace_dir = resolve_path(&project_dir, workspace_dir) - .to_str() - .unwrap() - .to_string(); - let target_paths = workspace - .into_iter() - .flat_map(|kv| kv.1) - .collect::>(); - HashMap::from([(workspace_dir, target_paths)]) - } else { - workspace - }; - self.workspaces_cache - .push(WorkspaceAnalysis::new(adapter, workspace)) + for adapter in adapter_commands.into_values() { + let AdapterConfiguration { + path, + extra_arg, + env, + include, + exclude, + workspace_dir, + .. + } = &adapter; + let file_paths = Self::project_files(&project_dir, include, exclude); + if file_paths.is_empty() { + continue; } + let mut adapter_command = Command::new(path); + let mut args_file_path: Vec<&str> = vec![]; + file_paths.iter().for_each(|file_path| { + args_file_path.push("--file-paths"); + args_file_path.push(file_path); + }); + let output = adapter_command + .arg("detect-workspace") + .args(args_file_path) + .arg("--") + .args(extra_arg) + .envs(env) + .output() + .map_err(|err| LSError::Adapter(err.to_string()))?; + let adapter_result = String::from_utf8(output.stdout) + .map_err(|err| LSError::Adapter(err.to_string()))?; + let workspace: DetectWorkspaceResult = match serde_json::from_str(&adapter_result) { + Ok(result) => result, + Err(err) => { + let stderr = String::from_utf8(output.stderr); + tracing::error!("Failed to parse adapter result: {:?}", err); + tracing::error!("Error: {:?}", stderr); + return Err(LSError::Adapter(err.to_string())); + } + }; + let workspace = if let Some(workspace_dir) = workspace_dir { + let workspace_dir = resolve_path(&project_dir, workspace_dir) + .to_str() + .unwrap() + .to_string(); + let target_paths = workspace + .into_iter() + .flat_map(|kv| kv.1) + .collect::>(); + HashMap::from([(workspace_dir, target_paths)]) + } else { + workspace + }; + self.workspaces_cache + .push(WorkspaceAnalysis::new(adapter, workspace)) } tracing::info!("workspaces_cache={:#?}", self.workspaces_cache); send_stdout(&json!({ @@ -497,7 +495,7 @@ mod tests { name: "demo".to_string(), }]), options: InitializedOptions { - adapter_command: HashMap::from([(String::from(".rs"), vec![])]), + adapter_command: HashMap::new(), enable_workspace_diagnostics: Some(true), }, workspaces_cache: Vec::new(), @@ -527,7 +525,7 @@ mod tests { name: "demo".to_string(), }]), options: InitializedOptions { - adapter_command: HashMap::from([(String::from(".rs"), vec![adapter_conf])]), + adapter_command: HashMap::from([(String::from(".rs"), adapter_conf)]), enable_workspace_diagnostics: Some(true), }, workspaces_cache: Vec::new(), @@ -592,7 +590,7 @@ mod tests { name: "demo".to_string(), }]), options: InitializedOptions { - adapter_command: HashMap::from([(String::from(".rs"), vec![adapter_conf.clone()])]), + adapter_command: HashMap::from([(String::from(".rs"), adapter_conf.clone())]), enable_workspace_diagnostics: Some(true), }, workspaces_cache: Vec::new(), From fa78f5faecba73b813f3015b761d74d73c369ad3 Mon Sep 17 00:00:00 2001 From: kbwo Date: Fri, 25 Oct 2024 00:42:11 +0900 Subject: [PATCH 090/139] chore(demo): update editor config according to previous schema change --- .vim/coc-settings.json | 16 +++--- demo/.helix/config.toml | 3 + demo/.vim/coc-settings.json | 112 ++++++++++++++++-------------------- demo/.vscode/settings.json | 98 ++++++++++++++----------------- 4 files changed, 100 insertions(+), 129 deletions(-) create mode 100644 demo/.helix/config.toml diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json index cd55328..078d090 100644 --- a/.vim/coc-settings.json +++ b/.vim/coc-settings.json @@ -2,15 +2,13 @@ "testing.enable": true, "testing.fileTypes": ["rust"], "testing.adapterCommand": { - "rust": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-test", "--workspace"], - "include": ["/**/*.rs"], - "exclude": ["/demo/**/*"], - "workspace_dir": "." - } - ] + "rust": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=cargo-test", "--workspace"], + "include": ["/**/*.rs"], + "exclude": ["/demo/**/*"], + "workspace_dir": "." + } }, "testing.enableWorkspaceDiagnostics": true, "testing.server.path": "testing-language-server", diff --git a/demo/.helix/config.toml b/demo/.helix/config.toml new file mode 100644 index 0000000..adfa957 --- /dev/null +++ b/demo/.helix/config.toml @@ -0,0 +1,3 @@ +[editor.soft-wrap] +enable = true +max-wrap = 25 # increase value to reduce forced mid-word wrapping diff --git a/demo/.vim/coc-settings.json b/demo/.vim/coc-settings.json index 79ac54b..625b7c4 100644 --- a/demo/.vim/coc-settings.json +++ b/demo/.vim/coc-settings.json @@ -6,70 +6,54 @@ "filetypes": ["rust", "javascript", "go", "typescript", "php"], "initializationOptions": { "adapterCommand": { - "cargo-test": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-test"], - "include": ["/**/src/**/*.rs"], - "exclude": ["/**/target/**"] - } - ], - "cargo-nextest": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-nextest"], - "include": ["/**/src/**/*.rs"], - "exclude": ["/**/target/**"] - } - ], - "jest": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=jest"], - "include": ["/jest/*.js"], - "exclude": ["/jest/**/node_modules/**/*"] - } - ], - "vitest": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=vitest"], - "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], - "exclude": ["/vitest/**/node_modules/**/*"] - } - ], - "deno": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=deno"], - "include": ["/deno/*.ts"], - "exclude": [] - } - ], - "go": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=go-test"], - "include": ["/**/*.go"], - "exclude": [] - } - ], - "node-test": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=node-test"], - "include": ["/node-test/*.test.js"], - "exclude": [] - } - ], - "phpunit": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=phpunit"], - "include": ["/**/*Test.php"], - "exclude": ["/phpunit/vendor/**/*.php"] - } - ] + "cargo-test": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=cargo-test"], + "include": ["/**/src/**/*.rs"], + "exclude": ["/**/target/**"] + }, + "cargo-nextest": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=cargo-nextest"], + "include": ["/**/src/**/*.rs"], + "exclude": ["/**/target/**"] + }, + "jest": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=jest"], + "include": ["/jest/*.js"], + "exclude": ["/jest/**/node_modules/**/*"] + }, + "vitest": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=vitest"], + "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], + "exclude": ["/vitest/**/node_modules/**/*"] + }, + "deno": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=deno"], + "include": ["/deno/*.ts"], + "exclude": [] + }, + "go": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=go-test"], + "include": ["/**/*.go"], + "exclude": [] + }, + "node-test": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=node-test"], + "include": ["/node-test/*.test.js"], + "exclude": [] + }, + "phpunit": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=phpunit"], + "include": ["/**/*Test.php"], + "exclude": ["/phpunit/vendor/**/*.php"] + } } } } diff --git a/demo/.vscode/settings.json b/demo/.vscode/settings.json index 6e33949..59f6ef5 100644 --- a/demo/.vscode/settings.json +++ b/demo/.vscode/settings.json @@ -2,62 +2,48 @@ "testing.enable": true, "filetypes": ["rust", "javascript", "go", "typescript", "php"], "testing.adapterCommand": { - "cargo-nextest": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-nextest"], - "include": ["/**/src/**/*.rs"], - "exclude": ["/**/target/**"] - } - ], - "jest": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=jest"], - "include": ["/jest/*.js"], - "exclude": ["/jest/**/node_modules/**/*"] - } - ], - "vitest": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=vitest"], - "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], - "exclude": ["/vitest/**/node_modules/**/*"] - } - ], - "deno": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=deno"], - "include": ["/deno/*.ts"], - "exclude": [] - } - ], - "go": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=go-test"], - "include": ["/**/*.go"], - "exclude": [] - } - ], - "node-test": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=node-test"], - "include": ["/node-test/*.test.js"], - "exclude": [] - } - ], - "phpunit": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=phpunit"], - "include": ["/**/*Test.php"], - "exclude": ["/phpunit/vendor/**/*.php"] - } - ] + "cargo-nextest": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=cargo-nextest"], + "include": ["/**/src/**/*.rs"], + "exclude": ["/**/target/**"] + }, + "jest": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=jest"], + "include": ["/jest/*.js"], + "exclude": ["/jest/**/node_modules/**/*"] + }, + "vitest": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=vitest"], + "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], + "exclude": ["/vitest/**/node_modules/**/*"] + }, + "deno": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=deno"], + "include": ["/deno/*.ts"], + "exclude": [] + }, + "go": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=go-test"], + "include": ["/**/*.go"], + "exclude": [] + }, + "node-test": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=node-test"], + "include": ["/node-test/*.test.js"], + "exclude": [] + }, + "phpunit": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=phpunit"], + "include": ["/**/*Test.php"], + "exclude": ["/phpunit/vendor/**/*.php"] + } }, "testing.enableWorkspaceDiagnostics": true, "testing.server.path": "testing-language-server", From 5211310b7fde7e9b0f1f4c83ff0d1cd028ca954d Mon Sep 17 00:00:00 2001 From: kbwo Date: Fri, 25 Oct 2024 00:30:19 +0900 Subject: [PATCH 091/139] chore(demo): add example config of helix --- demo/.helix/languages.toml | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 demo/.helix/languages.toml diff --git a/demo/.helix/languages.toml b/demo/.helix/languages.toml new file mode 100644 index 0000000..d18c438 --- /dev/null +++ b/demo/.helix/languages.toml @@ -0,0 +1,49 @@ +[language-server.testing-ls] +command = "testing-language-server" +args = [] + +[language-server.testing-ls.config.adapterCommand] +cargo-test = [ + { path = "testing-ls-adapter", extra_arg = ["--test-kind=cargo-test"], include = ["/**/src/**/*.rs"], exclude = ["/**/target/**"] } +] +cargo-nextest = [ + { path = "testing-ls-adapter", extra_arg = ["--test-kind=cargo-nextest"], include = ["/**/src/**/*.rs"], exclude = ["/**/target/**"] } +] +jest = [ + { path = "testing-ls-adapter", extra_arg = ["--test-kind=jest"], include = ["/jest/*.js"], exclude = ["/jest/**/node_modules/**/*"] } +] +vitest = [ + { path = "testing-ls-adapter", extra_arg = ["--test-kind=vitest"], include = ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], exclude = ["/vitest/**/node_modules/**/*"] } +] +deno = [ + { path = "testing-ls-adapter", extra_arg = ["--test-kind=deno"], include = ["/deno/*.ts"], exclude = [] } +] +go = [ + { path = "testing-ls-adapter", extra_arg = ["--test-kind=go-test"], include = ["/**/*.go"], exclude = [] } +] +node-test = [ + { path = "testing-ls-adapter", extra_arg = ["--test-kind=node-test"], include = ["/node-test/*.test.js"], exclude = [] } +] +phpunit = [ + { path = "testing-ls-adapter", extra_arg = ["--test-kind=phpunit"], include = ["/**/*Test.php"], exclude = ["/phpunit/vendor/**/*.php"] } +] + +[[language]] +name = "rust" +language-servers = [ { name = "testing-ls", only-features = [ "diagnostics" ] }, "rust-analyzer" ] + +[[language]] +name = "typescript" +language-servers = [ { name = "testing-ls", only-features = [ "diagnostics" ] }, "typescript-language-server" ] + +[[language]] +name = "php" +language-servers = [ { name = "testing-ls", only-features = [ "diagnostics" ] }, "phpactor" ] + +[[language]] +name = "go" +language-servers = [ { name = "testing-ls", only-features = [ "diagnostics" ] }, "gopls" ] + +[[language]] +name = "javascript" +language-servers = [ { name = "testing-ls", only-features = [ "diagnostics" ] }, "typescript-language-server" ] \ No newline at end of file From c6d839395d339099bdbfd74e8926d99a80fa632f Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 30 Oct 2024 23:37:00 +0900 Subject: [PATCH 092/139] doc: update README --- README.md | 111 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 77ffafe..9419810 100644 --- a/README.md +++ b/README.md @@ -26,51 +26,98 @@ cargo install testing-ls-adapter - [x] Realtime testing diagnostics - [x] [VSCode extension](https://github.com/kbwo/vscode-testing-ls) -- [x] [Coc.nvim extension](https://github.com/kbwo/coc-testing-ls) +- [x] [coc.nvim extension](https://github.com/kbwo/coc-testing-ls) - [x] For Neovim builtin LSP, see [demo/README.md](./demo/README.md) - [ ] More efficient checking of diagnostics - [ ] Useful commands in each extension ## Configuration -language server config: +### VSCode -``` -"languageserver": { - "testing": { - "command": "/testing-language-server", - "trace.server": "verbose", - "filetypes": [ - "rust", - "javascript" - ], - "initializationOptions": { - "initializationOptions": { - "adapterCommand": { - "cargo test": [ - { - "path": "/testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-test"], - "include": ["**/*.rs"], - "exclude": ["**/target/**"] - } - ], - "jest": [ - { - "path": "/testing-ls-adapter", - "extra_arg": ["--test-kind=jest"], - "include": ["/**/*.js"], - "exclude": ["/node_modules/**/*"] - } - ] +Install from [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=kbwo.testing-language-server). +You should set `adapterCommand` in `initializationOptions` for each project. +You can see the example in [settings.json](./demo/.vscode/settings.json). + + +### coc.nvim +Install from `:CocInstall coc-testing-ls`. +You should set `adapterCommand` in `initializationOptions` for each project. +You can see the example in [See more example](./demo/.vim/coc-settings.json) + +### Neovim (nvim-lspconfig) + +```lua +local lspconfig = require('lspconfig') +local configs = require('lspconfig.configs') +local util = require "lspconfig/util" + +configs.testing_ls = { + default_config = { + cmd = { "testing-language-server" }, + filetypes = { "rust" }, + root_dir = util.root_pattern(".git", "Cargo.toml"), + init_options = { + enable = true, + fileTypes = {"rust"}, + adapterCommand = { + -- See test execution settings for each project + -- This configuration assumes a Rust project + rust = { + path = "testing-ls-adapter", + extra_arg = { "--test-kind=cargo-test", "--workspace" }, + include = { "/demo/**/src/**/*.rs"}, + exclude = { "/**/target/**"}, + } + }, + enableWorkspaceDiagnostics = true, + trace = { + server = "verbose" } } + }, + docs = { + description = [[ + https://github.com/kbwo/testing-language-server + + Language Server for real-time testing. + ]], + }, +} + +lspconfig.testing_ls.setup{} +``` + + +## ⚠️ Breaking Changes (2024-10-25) + +The configuration structure for adapter commands has been changed: + +**Before:** +```json +"adapterCommand": { + "rust": [ + { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=cargo-test"] + // ... } + ] +} +``` + +**After:** +```json +"adapterCommand": { + "rust": { + "path": "testing-ls-adapter", + "extra_arg": ["--test-kind=cargo-test"] + // ... } } ``` -[See more example](./demo/.vim/coc-settings.json) +The array wrapper has been removed to simplify the configuration structure. Please update your settings accordingly. ## Adapter - [x] `cargo test` @@ -85,4 +132,4 @@ language server config: ### Writing custom adapter ⚠ The specification of adapter CLI is not stabilized yet. -See [ADAPTER_SPEC.md](./doc/ADAPTER_SPEC.md) and [spec.rs](./src/spec.rs). +See [ADAPTER_SPEC.md](./doc/ADAPTER_SPEC.md) and [spec.rs](./src/spec.rs). \ No newline at end of file From 6dff68d23a5cb79283d0cb06486dba3445af724a Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 30 Oct 2024 23:45:39 +0900 Subject: [PATCH 093/139] doc: update README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 9419810..528d49f 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,9 @@ configs.testing_ls = { lspconfig.testing_ls.setup{} ``` +### Helix +See [language.toml](./demo/.helix/language.toml). + ## ⚠️ Breaking Changes (2024-10-25) From 92dec010a852c289aafba606eb48c1cc5c3d4eac Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 30 Oct 2024 23:46:18 +0900 Subject: [PATCH 094/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14ad310..1b17217 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,7 +717,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.0.15" +version = "0.1.1" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index e316719..28dc665 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.0.15" +version = "0.1.1" edition = "2021" description = "LSP server for testing" license = "MIT" From 575f3ee661d33096632f79636db2095611c4dada Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 9 Nov 2024 18:11:33 +0900 Subject: [PATCH 095/139] feat: get configuration from toml file --- .testingls.toml | 15 +++++++++ Cargo.lock | 75 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + demo/.testingls.toml | 49 +++++++++++++++++++++++++++++ src/server.rs | 20 ++++++++---- 5 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 .testingls.toml create mode 100644 demo/.testingls.toml diff --git a/.testingls.toml b/.testingls.toml new file mode 100644 index 0000000..00f33f1 --- /dev/null +++ b/.testingls.toml @@ -0,0 +1,15 @@ +enableWorkspaceDiagnostics = true + +[adapterCommand.rust] +path = "testing-ls-adapter" +extra_arg = [ + "--test-kind=cargo-test", + "--workspace" +] +include = [ + "/**/*.rs" +] +exclude = [ + "/demo/**/*" +] +workspace_dir = "." diff --git a/Cargo.lock b/Cargo.lock index 1b17217..45f51a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -256,6 +256,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.8" @@ -322,6 +328,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + [[package]] name = "heck" version = "0.4.1" @@ -383,6 +395,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "itoa" version = "1.0.11" @@ -630,6 +652,15 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -732,6 +763,7 @@ dependencies = [ "serde_json", "strum", "thiserror", + "toml", "tracing", "tracing-appender", "tracing-subscriber", @@ -838,6 +870,40 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.40" @@ -1209,6 +1275,15 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "xml-rs" version = "0.8.21" diff --git a/Cargo.toml b/Cargo.toml index 28dc665..e287420 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,3 +48,4 @@ glob = { workspace = true } globwalk = "0.9.1" tree-sitter-php = "0.22.8" chrono = "0.4.38" +toml = "0.8.19" diff --git a/demo/.testingls.toml b/demo/.testingls.toml new file mode 100644 index 0000000..014f055 --- /dev/null +++ b/demo/.testingls.toml @@ -0,0 +1,49 @@ +enableWorkspaceDiagnostics = true + +[adapterCommand.cargo-test] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=cargo-test"] +include = ["/**/src/**/*.rs"] +exclude = ["/**/target/**"] + +[adapterCommand.cargo-nextest] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=cargo-nextest"] +include = ["/**/src/**/*.rs"] +exclude = ["/**/target/**"] + +[adapterCommand.jest] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=jest"] +include = ["/jest/*.js"] +exclude = ["/jest/**/node_modules/**/*"] + +[adapterCommand.vitest] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=vitest"] +include = ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"] +exclude = ["/vitest/**/node_modules/**/*"] + +[adapterCommand.deno] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=deno"] +include = ["/deno/*.ts"] +exclude = [] + +[adapterCommand.go] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=go-test"] +include = ["/**/*.go"] +exclude = [] + +[adapterCommand.node-test] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=node-test"] +include = ["/node-test/*.test.js"] +exclude = [] + +[adapterCommand.phpunit] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=phpunit"] +include = ["/**/*Test.php"] +exclude = ["/phpunit/vendor/**/*.php"] diff --git a/src/server.rs b/src/server.rs index c9d6405..60f5d65 100644 --- a/src/server.rs +++ b/src/server.rs @@ -136,12 +136,20 @@ impl TestingLS { &self, options: Option<&Value>, ) -> Result { - if let Some(options) = options { - Ok(serde_json::from_value(options.clone())?) - } else { - Err(LSError::Any(anyhow::anyhow!( - "Invalid initialization options" - ))) + let project_dir = self.project_dir()?; + let toml_path = project_dir.join(".testingls.toml"); + let toml_content = std::fs::read_to_string(toml_path); + match toml_content { + Ok(toml_content) => Ok(toml::from_str::(&toml_content).unwrap()), + Err(_) => { + if let Some(options) = options { + Ok(serde_json::from_value(options.clone())?) + } else { + Err(LSError::Any(anyhow::anyhow!( + "Invalid initialization options" + ))) + } + } } } From f20cb7f16b5b6033b01c3b59431c88cea9dbb7de Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 9 Nov 2024 18:19:01 +0900 Subject: [PATCH 096/139] feat: workspace diagnostics even when no `workspace/diagnostic` request --- src/main.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main.rs b/src/main.rs index 260a9c1..e7e4ab2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,7 @@ fn extract_uri(params: &Value) -> Result { } fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { + let mut is_workspace_checked = false; loop { let mut size = 0; 'read_header: loop { @@ -93,6 +94,7 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { std::process::exit(0); } "workspace/diagnostic" => { + is_workspace_checked = true; server.diagnose_workspace()?; } "textDocument/diagnostic" | "textDocument/didSave" => { @@ -100,6 +102,10 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { server.check_file(&uri, false)?; } "textDocument/didOpen" => { + if !is_workspace_checked { + is_workspace_checked = true; + server.diagnose_workspace()?; + } let uri = extract_textdocument_uri(params)?; if server.refreshing_needed(&uri) { server.refresh_workspaces_cache()?; From 6f1fc1f03a9f38fce03ee7ac19186332d2172a9c Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 10 Nov 2024 15:11:25 +0900 Subject: [PATCH 097/139] chore: update each settings for demo --- .vim/coc-settings.json | 10 ---- README.md | 111 +++++++++++++++++++----------------- demo/.helix/languages.toml | 26 --------- demo/.vim/coc-settings.json | 61 +++----------------- demo/.vscode/settings.json | 52 +++-------------- 5 files changed, 73 insertions(+), 187 deletions(-) diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json index 078d090..677d5ba 100644 --- a/.vim/coc-settings.json +++ b/.vim/coc-settings.json @@ -1,15 +1,5 @@ { "testing.enable": true, - "testing.fileTypes": ["rust"], - "testing.adapterCommand": { - "rust": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-test", "--workspace"], - "include": ["/**/*.rs"], - "exclude": ["/demo/**/*"], - "workspace_dir": "." - } - }, "testing.enableWorkspaceDiagnostics": true, "testing.server.path": "testing-language-server", "testing.trace.server": "verbose" diff --git a/README.md b/README.md index 528d49f..da96906 100644 --- a/README.md +++ b/README.md @@ -33,17 +33,69 @@ cargo install testing-ls-adapter ## Configuration +### Required settings for all editors +You need to prepare .testingls.toml. See [this](./demo/.testingls.toml) for an example of the configuration. + +```.testingls.toml +enableWorkspaceDiagnostics = true + +[adapterCommand.cargo-test] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=cargo-test"] +include = ["/**/src/**/*.rs"] +exclude = ["/**/target/**"] + +[adapterCommand.cargo-nextest] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=cargo-nextest"] +include = ["/**/src/**/*.rs"] +exclude = ["/**/target/**"] + +[adapterCommand.jest] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=jest"] +include = ["/jest/*.js"] +exclude = ["/jest/**/node_modules/**/*"] + +[adapterCommand.vitest] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=vitest"] +include = ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"] +exclude = ["/vitest/**/node_modules/**/*"] + +[adapterCommand.deno] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=deno"] +include = ["/deno/*.ts"] +exclude = [] + +[adapterCommand.go] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=go-test"] +include = ["/**/*.go"] +exclude = [] + +[adapterCommand.node-test] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=node-test"] +include = ["/node-test/*.test.js"] +exclude = [] + +[adapterCommand.phpunit] +path = "testing-ls-adapter" +extra_arg = ["--test-kind=phpunit"] +include = ["/**/*Test.php"] +exclude = ["/phpunit/vendor/**/*.php"] +``` + ### VSCode Install from [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=kbwo.testing-language-server). -You should set `adapterCommand` in `initializationOptions` for each project. You can see the example in [settings.json](./demo/.vscode/settings.json). - ### coc.nvim Install from `:CocInstall coc-testing-ls`. -You should set `adapterCommand` in `initializationOptions` for each project. -You can see the example in [See more example](./demo/.vim/coc-settings.json) +You can see the example in [See more example](./.vim/coc-settings.json) ### Neovim (nvim-lspconfig) @@ -55,26 +107,8 @@ local util = require "lspconfig/util" configs.testing_ls = { default_config = { cmd = { "testing-language-server" }, - filetypes = { "rust" }, - root_dir = util.root_pattern(".git", "Cargo.toml"), - init_options = { - enable = true, - fileTypes = {"rust"}, - adapterCommand = { - -- See test execution settings for each project - -- This configuration assumes a Rust project - rust = { - path = "testing-ls-adapter", - extra_arg = { "--test-kind=cargo-test", "--workspace" }, - include = { "/demo/**/src/**/*.rs"}, - exclude = { "/**/target/**"}, - } - }, - enableWorkspaceDiagnostics = true, - trace = { - server = "verbose" - } - } + filetypes = {}, + root_dir = util.root_pattern(".testingls.toml", ".git" ), }, docs = { description = [[ @@ -91,35 +125,6 @@ lspconfig.testing_ls.setup{} ### Helix See [language.toml](./demo/.helix/language.toml). - -## ⚠️ Breaking Changes (2024-10-25) - -The configuration structure for adapter commands has been changed: - -**Before:** -```json -"adapterCommand": { - "rust": [ - { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-test"] - // ... - } - ] -} -``` - -**After:** -```json -"adapterCommand": { - "rust": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-test"] - // ... - } -} -``` - The array wrapper has been removed to simplify the configuration structure. Please update your settings accordingly. ## Adapter diff --git a/demo/.helix/languages.toml b/demo/.helix/languages.toml index d18c438..1412674 100644 --- a/demo/.helix/languages.toml +++ b/demo/.helix/languages.toml @@ -2,32 +2,6 @@ command = "testing-language-server" args = [] -[language-server.testing-ls.config.adapterCommand] -cargo-test = [ - { path = "testing-ls-adapter", extra_arg = ["--test-kind=cargo-test"], include = ["/**/src/**/*.rs"], exclude = ["/**/target/**"] } -] -cargo-nextest = [ - { path = "testing-ls-adapter", extra_arg = ["--test-kind=cargo-nextest"], include = ["/**/src/**/*.rs"], exclude = ["/**/target/**"] } -] -jest = [ - { path = "testing-ls-adapter", extra_arg = ["--test-kind=jest"], include = ["/jest/*.js"], exclude = ["/jest/**/node_modules/**/*"] } -] -vitest = [ - { path = "testing-ls-adapter", extra_arg = ["--test-kind=vitest"], include = ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], exclude = ["/vitest/**/node_modules/**/*"] } -] -deno = [ - { path = "testing-ls-adapter", extra_arg = ["--test-kind=deno"], include = ["/deno/*.ts"], exclude = [] } -] -go = [ - { path = "testing-ls-adapter", extra_arg = ["--test-kind=go-test"], include = ["/**/*.go"], exclude = [] } -] -node-test = [ - { path = "testing-ls-adapter", extra_arg = ["--test-kind=node-test"], include = ["/node-test/*.test.js"], exclude = [] } -] -phpunit = [ - { path = "testing-ls-adapter", extra_arg = ["--test-kind=phpunit"], include = ["/**/*Test.php"], exclude = ["/phpunit/vendor/**/*.php"] } -] - [[language]] name = "rust" language-servers = [ { name = "testing-ls", only-features = [ "diagnostics" ] }, "rust-analyzer" ] diff --git a/demo/.vim/coc-settings.json b/demo/.vim/coc-settings.json index 625b7c4..53f30f0 100644 --- a/demo/.vim/coc-settings.json +++ b/demo/.vim/coc-settings.json @@ -3,59 +3,14 @@ "testing": { "command": "testing-language-server", "trace.server": "verbose", - "filetypes": ["rust", "javascript", "go", "typescript", "php"], - "initializationOptions": { - "adapterCommand": { - "cargo-test": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-test"], - "include": ["/**/src/**/*.rs"], - "exclude": ["/**/target/**"] - }, - "cargo-nextest": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-nextest"], - "include": ["/**/src/**/*.rs"], - "exclude": ["/**/target/**"] - }, - "jest": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=jest"], - "include": ["/jest/*.js"], - "exclude": ["/jest/**/node_modules/**/*"] - }, - "vitest": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=vitest"], - "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], - "exclude": ["/vitest/**/node_modules/**/*"] - }, - "deno": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=deno"], - "include": ["/deno/*.ts"], - "exclude": [] - }, - "go": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=go-test"], - "include": ["/**/*.go"], - "exclude": [] - }, - "node-test": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=node-test"], - "include": ["/node-test/*.test.js"], - "exclude": [] - }, - "phpunit": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=phpunit"], - "include": ["/**/*Test.php"], - "exclude": ["/phpunit/vendor/**/*.php"] - } - } - } + "filetypes": [ + "rust", + "javascript", + "go", + "typescript", + "php" + ], + "initializationOptions": {} } }, "deno.enable": false, diff --git a/demo/.vscode/settings.json b/demo/.vscode/settings.json index 59f6ef5..0ba72a8 100644 --- a/demo/.vscode/settings.json +++ b/demo/.vscode/settings.json @@ -1,50 +1,12 @@ { "testing.enable": true, - "filetypes": ["rust", "javascript", "go", "typescript", "php"], - "testing.adapterCommand": { - "cargo-nextest": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=cargo-nextest"], - "include": ["/**/src/**/*.rs"], - "exclude": ["/**/target/**"] - }, - "jest": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=jest"], - "include": ["/jest/*.js"], - "exclude": ["/jest/**/node_modules/**/*"] - }, - "vitest": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=vitest"], - "include": ["/vitest/*.test.ts", "/vitest/config/**/*.test.ts"], - "exclude": ["/vitest/**/node_modules/**/*"] - }, - "deno": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=deno"], - "include": ["/deno/*.ts"], - "exclude": [] - }, - "go": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=go-test"], - "include": ["/**/*.go"], - "exclude": [] - }, - "node-test": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=node-test"], - "include": ["/node-test/*.test.js"], - "exclude": [] - }, - "phpunit": { - "path": "testing-ls-adapter", - "extra_arg": ["--test-kind=phpunit"], - "include": ["/**/*Test.php"], - "exclude": ["/phpunit/vendor/**/*.php"] - } - }, + "filetypes": [ + "rust", + "javascript", + "go", + "typescript", + "php" + ], "testing.enableWorkspaceDiagnostics": true, "testing.server.path": "testing-language-server", "testing.trace.server": "verbose" From 33f44e5bad21daa04c0b77d63699cbd0ac3101cd Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 10 Nov 2024 15:45:41 +0900 Subject: [PATCH 098/139] refactor: tiny fix --- src/server.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server.rs b/src/server.rs index 60f5d65..a81fb3a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -14,6 +14,8 @@ use std::path::PathBuf; use std::process::Command; use std::process::Output; +const TOML_FILE_NAME: &str = ".testingls.toml"; + #[derive(Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct InitializedOptions { @@ -137,7 +139,7 @@ impl TestingLS { options: Option<&Value>, ) -> Result { let project_dir = self.project_dir()?; - let toml_path = project_dir.join(".testingls.toml"); + let toml_path = project_dir.join(TOML_FILE_NAME); let toml_content = std::fs::read_to_string(toml_path); match toml_content { Ok(toml_content) => Ok(toml::from_str::(&toml_content).unwrap()), From b8054f6594ca888c4a6a9f98c985dc3df79378d9 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sun, 10 Nov 2024 15:52:37 +0900 Subject: [PATCH 099/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45f51a2..9d930d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -748,7 +748,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.1" +version = "0.1.2" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index e287420..4a6994a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.1" +version = "0.1.2" edition = "2021" description = "LSP server for testing" license = "MIT" From b87e2b9123dad40d82bce0516de8343bed13eebc Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 19 Nov 2024 19:45:23 +0900 Subject: [PATCH 100/139] fix: prevent syncing text documents --- src/server.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/server.rs b/src/server.rs index a81fb3a..6827887 100644 --- a/src/server.rs +++ b/src/server.rs @@ -127,9 +127,6 @@ impl TestingLS { workspace_diagnostics: true, work_done_progress_options: WorkDoneProgressOptions::default(), })), - text_document_sync: Some(TextDocumentSyncCapability::Kind( - TextDocumentSyncKind::INCREMENTAL, - )), ..ServerCapabilities::default() } } From df735e9836613f02eda10a6cc138e23591d4f143 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 19 Nov 2024 19:47:08 +0900 Subject: [PATCH 101/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d930d9..633511b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -748,7 +748,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.2" +version = "0.1.3" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 4a6994a..4b2b631 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.2" +version = "0.1.3" edition = "2021" description = "LSP server for testing" license = "MIT" From aefd8437ffb688c92f6ca87657268ba8a77560ee Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 19 Nov 2024 23:16:24 +0900 Subject: [PATCH 102/139] feat: diagnose workspace after initialization --- src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.rs b/src/main.rs index e7e4ab2..857a8dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -85,6 +85,8 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { let initialize_params = InitializeParams::deserialize(params)?; let id = value["id"].as_i64().unwrap(); server.initialize(id, initialize_params)?; + is_workspace_checked = true; + server.diagnose_workspace()?; } "shutdown" => { let id = value["id"].as_i64().unwrap(); From 533c5106e348fff8513a9fce76e6824e807048b3 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 19 Nov 2024 23:17:15 +0900 Subject: [PATCH 103/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 633511b..23c7cba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -748,7 +748,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.3" +version = "0.1.4" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 4b2b631..53c7911 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.3" +version = "0.1.4" edition = "2021" description = "LSP server for testing" license = "MIT" From c939c3c5e0b65e9d40967ce997ec0703f3968a29 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 20 Nov 2024 01:07:27 +0900 Subject: [PATCH 104/139] fix: handle unexpected request method correctly --- src/main.rs | 12 +++++++++++- src/util.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 857a8dc..bf5bf52 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ use util::{format_uri, send_stdout}; use crate::log::Log; use crate::server::TestingLS; +use crate::util::send_error; fn extract_textdocument_uri(params: &Value) -> Result { let uri = params["textDocument"]["uri"] @@ -81,6 +82,7 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { if let Some(method) = method { match *method { + "initialized" | "$/cancelRequest" => {} "initialize" => { let initialize_params = InitializeParams::deserialize(params)?; let id = value["id"].as_i64().unwrap(); @@ -130,7 +132,15 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { "result": result, }))?; } - _ => {} + _ => { + // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#responseMessage + let id = value["id"].as_i64(); + send_error( + id, + -32601, // Method not found + format!("method not found: {}", method), + )?; + } } } } diff --git a/src/util.rs b/src/util.rs index c076b4e..0947ada 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,11 @@ use crate::error::LSError; use chrono::NaiveDate; use chrono::Utc; +use serde::Deserialize; use serde::Serialize; +use serde_json::json; +use serde_json::Number; +use serde_json::Value; use std::fs; use std::io::stdout; use std::io::Write; @@ -20,6 +24,31 @@ where Ok(()) } +#[derive(Debug, Serialize, Deserialize)] +pub struct ErrorMessage { + jsonrpc: String, + id: Option, + pub error: Value, +} + +impl ErrorMessage { + #[allow(dead_code)] + pub fn new>(id: Option, error: Value) -> Self { + Self { + jsonrpc: "2.0".into(), + id: id.map(|i| i.into()), + error, + } + } +} + +pub fn send_error>(id: Option, code: i64, msg: S) -> Result<(), LSError> { + send_stdout(&ErrorMessage::new( + id, + json!({ "code": code, "message": msg.into() }), + )) +} + pub fn format_uri(uri: &str) -> String { uri.replace("file://", "") } From c61aaac03e5bc3eaea454f1914bdcee1fd10fe20 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 20 Nov 2024 01:09:38 +0900 Subject: [PATCH 105/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23c7cba..c1b6d25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -748,7 +748,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.4" +version = "0.1.5" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 53c7911..f9ccfd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.4" +version = "0.1.5" edition = "2021" description = "LSP server for testing" license = "MIT" From c5fe76295db5fb829b19f3e8eb83dbbf3e0f3819 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 20 Nov 2024 19:23:17 +0900 Subject: [PATCH 106/139] fix: handle errors correctly --- src/main.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main.rs b/src/main.rs index bf5bf52..93ec957 100644 --- a/src/main.rs +++ b/src/main.rs @@ -82,13 +82,15 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { if let Some(method) = method { match *method { - "initialized" | "$/cancelRequest" => {} + "$/cancelRequest" => {} + "initialized" => { + is_workspace_checked = true; + server.diagnose_workspace()?; + } "initialize" => { let initialize_params = InitializeParams::deserialize(params)?; let id = value["id"].as_i64().unwrap(); server.initialize(id, initialize_params)?; - is_workspace_checked = true; - server.diagnose_workspace()?; } "shutdown" => { let id = value["id"].as_i64().unwrap(); @@ -135,11 +137,13 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { _ => { // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#responseMessage let id = value["id"].as_i64(); - send_error( - id, - -32601, // Method not found - format!("method not found: {}", method), - )?; + if id.is_some() { + send_error( + id, + -32601, // Method not found + format!("method not found: {}", method), + )?; + } } } } From 7563cd801c27bcac5c4229488e50709f5b91f121 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 20 Nov 2024 19:24:21 +0900 Subject: [PATCH 107/139] chore: update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1b6d25..76c14c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -748,7 +748,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.5" +version = "0.1.6" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index f9ccfd0..3d1ceb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.5" +version = "0.1.6" edition = "2021" description = "LSP server for testing" license = "MIT" From 115cca2ecf4870a77ee9d6ef5523b05bd2249ab4 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 20 Nov 2024 19:25:48 +0900 Subject: [PATCH 108/139] feat(cargo-test): handle `--nocapture` option --- crates/adapter/src/runner/cargo_test.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 3834c3c..e391911 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -79,10 +79,12 @@ impl Runner for CargoTestRunner { let output = test_result; write_result_log("cargo_test.log", &output)?; let Output { stdout, stderr, .. } = output; - if stdout.is_empty() && !stderr.is_empty() { + if stdout.is_empty() { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } - let test_result = String::from_utf8(stdout)?; + // When `--nocapture` option is set, stderr has some important information + // to parse test result + let test_result = String::from_utf8(stderr)? + &String::from_utf8(stdout)?; let diagnostics: RunFileTestResult = parse_diagnostics( &test_result, PathBuf::from_str(&workspace_root).unwrap(), From 16074f3b4a451c626e142c2995f567d8b8b0a679 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 20 Nov 2024 19:26:37 +0900 Subject: [PATCH 109/139] chore(adapter): update version --- Cargo.lock | 2 +- crates/adapter/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76c14c5..7561a70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -772,7 +772,7 @@ dependencies = [ [[package]] name = "testing-ls-adapter" -version = "0.0.9" +version = "0.0.10" dependencies = [ "anyhow", "clap", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index cadf73a..50162a7 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.9" +version = "0.0.10" edition = "2021" description = "testing-language-server adapter" license = "MIT" From e09a50d60c22dc91872c196519bfe248c8b496d1 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 30 Nov 2024 16:50:47 +0900 Subject: [PATCH 110/139] feat: change warning diagnostics to window/showMessage --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/server.rs | 66 +++++++-------------------------------------------- 3 files changed, 11 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7561a70..4783bd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -748,7 +748,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.6" +version = "0.1.7" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 3d1ceb4..af93e9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.6" +version = "0.1.7" edition = "2021" description = "LSP server for testing" license = "MIT" diff --git a/src/server.rs b/src/server.rs index 6827887..bd60bab 100644 --- a/src/server.rs +++ b/src/server.rs @@ -319,29 +319,17 @@ impl TestingLS { if !stderr.is_empty() { let message = "Cannot run test command: \n".to_string() + &String::from_utf8(stderr).unwrap(); - let placeholder_diagnostic = Diagnostic { - range: Range { - start: Position { - line: 0, - character: 0, - }, - end: Position { - line: 0, - character: 0, - }, - }, + let message_type = MessageType::ERROR; + let params: ShowMessageParams = ShowMessageParams { + typ: message_type, message, - severity: Some(DiagnosticSeverity::WARNING), - code_description: None, - code: None, - source: None, - tags: None, - related_information: None, - data: None, }; - for path in paths { - diagnostics.push((path.to_string(), vec![placeholder_diagnostic.clone()])); - } + send_stdout(&json!({ + "jsonrpc": "2.0", + "method": "window/showMessage", + "params": params, + })) + .unwrap(); } let adapter_result = @@ -575,42 +563,6 @@ mod tests { assert_eq!(files, vec![test_file.to_str().unwrap()]); } - #[test] - fn bubble_adapter_error() { - let adapter_conf: AdapterConfiguration = AdapterConfiguration { - path: std::env::current_dir() - .unwrap() - .join("target/debug/testing-ls-adapter") - .to_str() - .unwrap() - .to_string(), - extra_arg: vec!["--invalid-arg".to_string()], - ..Default::default() - }; - let abs_path_of_demo = std::env::current_dir().unwrap().join("demo/rust"); - let files = - TestingLS::project_files(&abs_path_of_demo.clone(), &["/**/*.rs".to_string()], &[]); - - let server = TestingLS { - workspace_folders: Some(vec![WorkspaceFolder { - uri: Url::from_file_path(&abs_path_of_demo).unwrap(), - name: "demo".to_string(), - }]), - options: InitializedOptions { - adapter_command: HashMap::from([(String::from(".rs"), adapter_conf.clone())]), - enable_workspace_diagnostics: Some(true), - }, - workspaces_cache: Vec::new(), - }; - let diagnostics = server - .get_diagnostics(&adapter_conf, abs_path_of_demo.to_str().unwrap(), &files) - .unwrap(); - assert_eq!(diagnostics.len(), 1); - let diagnostic = diagnostics.first().unwrap().1.first().unwrap(); - assert_eq!(diagnostic.severity.unwrap(), DiagnosticSeverity::WARNING); - assert!(diagnostic.message.contains("Cannot run test command:")); - } - #[test] fn skip_workspace_diagnostics() { let mut server = TestingLS { From aa4883e038af61a5f0840e64524fbef289345b18 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 30 Nov 2024 18:19:28 +0900 Subject: [PATCH 111/139] feat(adapter): add diagnostics to show which test failed --- Cargo.lock | 55 ++++++++++---------- crates/adapter/Cargo.toml | 4 +- crates/adapter/src/runner/cargo_nextest.rs | 58 +++++++++++++-------- crates/adapter/src/runner/cargo_test.rs | 57 ++++++++++++-------- crates/adapter/src/runner/util.rs | 60 +++++++++++++++++++--- demo/rust/src/lib.rs | 9 ++++ 6 files changed, 167 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4783bd6..8b06e43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -721,31 +721,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "testing-language-server" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c1a48aec4305834e4f80ad28dfe5bea8c98c0bb215a092eb2af15c4ac86efb7" -dependencies = [ - "anyhow", - "chrono", - "clap", - "dirs", - "glob", - "globwalk", - "lsp-types", - "once_cell", - "regex", - "serde", - "serde_json", - "strum", - "thiserror", - "tracing", - "tracing-appender", - "tracing-subscriber", - "tree-sitter-php", -] - [[package]] name = "testing-language-server" version = "0.1.7" @@ -770,9 +745,35 @@ dependencies = [ "tree-sitter-php", ] +[[package]] +name = "testing-language-server" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fae6ce9cb290e80814d1796e4207a0a0dc21c216807136d48b68c0f27be29b9" +dependencies = [ + "anyhow", + "chrono", + "clap", + "dirs", + "glob", + "globwalk", + "lsp-types", + "once_cell", + "regex", + "serde", + "serde_json", + "strum", + "thiserror", + "toml", + "tracing", + "tracing-appender", + "tracing-subscriber", + "tree-sitter-php", +] + [[package]] name = "testing-ls-adapter" -version = "0.0.10" +version = "0.0.11" dependencies = [ "anyhow", "clap", @@ -782,7 +783,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.0.11", + "testing-language-server 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 50162a7..5148bd1 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.10" +version = "0.0.11" edition = "2021" description = "testing-language-server adapter" license = "MIT" @@ -8,7 +8,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -testing-language-server = "0.0.11" +testing-language-server = "0.1.7" lsp-types = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index fea1680..202a2b9 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -8,6 +8,7 @@ use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::DiscoverResult; use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::TestItem; use crate::model::Runner; @@ -16,14 +17,6 @@ use super::util::discover_rust_tests; use super::util::parse_cargo_diagnostics; use super::util::write_result_log; -fn parse_diagnostics( - contents: &str, - workspace_root: PathBuf, - file_paths: &[String], -) -> RunFileTestResult { - parse_cargo_diagnostics(contents, workspace_root, file_paths) -} - fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]) } @@ -54,19 +47,16 @@ impl Runner for CargoNextestRunner { args: testing_language_server::spec::RunFileTestArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; - let tests = file_paths + let discovered_tests: Vec = file_paths .iter() - .map(|path| { - discover_rust_tests(path).map(|test_items| { - test_items - .into_iter() - .map(|item| item.id) - .collect::>() - }) - }) + .map(|path| discover_rust_tests(path)) .filter_map(Result::ok) .flatten() .collect::>(); + let test_ids = discovered_tests + .iter() + .map(|item| item.id.clone()) + .collect::>(); let workspace_root = args.workspace; let test_result = std::process::Command::new("cargo") .current_dir(&workspace_root) @@ -76,7 +66,7 @@ impl Runner for CargoNextestRunner { .arg("--no-fail-fast") .args(args.extra) .arg("--") - .args(tests) + .args(&test_ids) .output() .unwrap(); let output = test_result; @@ -91,10 +81,11 @@ impl Runner for CargoNextestRunner { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let test_result = String::from_utf8(stderr)?; - let diagnostics: RunFileTestResult = parse_diagnostics( + let diagnostics: RunFileTestResult = parse_cargo_diagnostics( &test_result, PathBuf::from_str(&workspace_root).unwrap(), &file_paths, + &discovered_tests, ); send_stdout(&diagnostics)?; Ok(()) @@ -115,7 +106,7 @@ impl Runner for CargoNextestRunner { #[cfg(test)] mod tests { use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; - use testing_language_server::spec::RunFileTestResultItem; + use testing_language_server::spec::{RunFileTestResultItem, TestItem}; use crate::runner::util::MAX_CHAR_LENGTH; @@ -142,10 +133,35 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace "#; let file_paths = vec!["/home/example/projects/rocks-lib/src/rocks/dependency.rs".to_string()]; - let diagnostics: RunFileTestResult = parse_diagnostics( + let test_items: Vec = vec![TestItem { + id: "rocks::dependency::tests::parse_dependency".to_string(), + name: "rocks::dependency::tests::parse_dependency".to_string(), + start_position: Range { + start: Position { + line: 85, + character: 63, + }, + end: Position { + line: 85, + character: MAX_CHAR_LENGTH, + }, + }, + end_position: Range { + start: Position { + line: 85, + character: 63, + }, + end: Position { + line: 85, + character: MAX_CHAR_LENGTH, + }, + }, + }]; + let diagnostics: RunFileTestResult = parse_cargo_diagnostics( fixture, PathBuf::from_str("/home/example/projects").unwrap(), &file_paths, + &test_items, ); let message = r#"called `Result::unwrap()` on an `Err` value: unexpected end of input while parsing min or version number Location: diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index e391911..bea62bd 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -8,6 +8,7 @@ use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::DiscoverResult; use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::TestItem; use crate::model::Runner; @@ -16,14 +17,6 @@ use super::util::discover_rust_tests; use super::util::parse_cargo_diagnostics; use super::util::write_result_log; -fn parse_diagnostics( - contents: &str, - workspace_root: PathBuf, - file_paths: &[String], -) -> RunFileTestResult { - parse_cargo_diagnostics(contents, workspace_root, file_paths) -} - fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]) } @@ -54,26 +47,23 @@ impl Runner for CargoTestRunner { args: testing_language_server::spec::RunFileTestArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; - let tests = file_paths + let discovered_tests: Vec = file_paths .iter() - .map(|path| { - discover_rust_tests(path).map(|test_items| { - test_items - .into_iter() - .map(|item| item.id) - .collect::>() - }) - }) + .map(|path| discover_rust_tests(path)) .filter_map(Result::ok) .flatten() .collect::>(); + let test_ids = discovered_tests + .iter() + .map(|item| item.id.clone()) + .collect::>(); let workspace_root = args.workspace; let test_result = std::process::Command::new("cargo") .current_dir(&workspace_root) .arg("test") .args(args.extra) .arg("--") - .args(tests) + .args(&test_ids) .output() .unwrap(); let output = test_result; @@ -85,10 +75,12 @@ impl Runner for CargoTestRunner { // When `--nocapture` option is set, stderr has some important information // to parse test result let test_result = String::from_utf8(stderr)? + &String::from_utf8(stdout)?; - let diagnostics: RunFileTestResult = parse_diagnostics( + + let diagnostics: RunFileTestResult = parse_cargo_diagnostics( &test_result, PathBuf::from_str(&workspace_root).unwrap(), &file_paths, + &discovered_tests, ); send_stdout(&diagnostics)?; Ok(()) @@ -136,10 +128,35 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace "#; let file_paths = vec!["/home/example/projects/rocks-lib/src/rocks/dependency.rs".to_string()]; - let diagnostics: RunFileTestResult = parse_diagnostics( + let test_items: Vec = vec![TestItem { + id: "rocks::dependency::tests::parse_dependency".to_string(), + name: "rocks::dependency::tests::parse_dependency".to_string(), + start_position: Range { + start: Position { + line: 85, + character: 63, + }, + end: Position { + line: 85, + character: MAX_CHAR_LENGTH, + }, + }, + end_position: Range { + start: Position { + line: 85, + character: 63, + }, + end: Position { + line: 85, + character: MAX_CHAR_LENGTH, + }, + }, + }]; + let diagnostics: RunFileTestResult = parse_cargo_diagnostics( fixture, PathBuf::from_str("/home/example/projects").unwrap(), &file_paths, + &test_items, ); let message = r#"called `Result::unwrap()` on an `Err` value: unexpected end of input while parsing min or version number Location: diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index b93a7ce..b598214 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -276,19 +276,35 @@ pub fn parse_cargo_diagnostics( contents: &str, workspace_root: PathBuf, file_paths: &[String], + test_items: &[TestItem], ) -> RunFileTestResult { let contents = contents.replace("\r\n", "\n"); let lines = contents.lines(); let mut result_map: HashMap> = HashMap::new(); for (i, line) in lines.clone().enumerate() { + // Example: + // thread 'server::tests::test_panic' panicked at src/server.rs:584:9: let re = Regex::new(r"thread '([^']+)' panicked at ([^:]+):(\d+):(\d+):").unwrap(); if let Some(m) = re.captures(line) { let mut message = String::new(); - let file = m.get(2).unwrap().as_str().to_string(); - if let Some(file_path) = file_paths - .iter() - .find(|path| path.contains(workspace_root.join(&file).to_str().unwrap())) - { + // :: + let id_with_file = m.get(1).unwrap().as_str().to_string(); + + // relaive path + let relative_file_path = m.get(2).unwrap().as_str().to_string(); + // name of the file without extension + let file_stem = Path::new(&relative_file_path) + .file_stem() + .unwrap() + .to_str() + .unwrap(); + let executed_test_id = id_with_file.replace(&(file_stem.to_string() + "::"), ""); + + if let Some(file_path) = file_paths.iter().find(|path| { + path.contains(workspace_root.join(&relative_file_path).to_str().unwrap()) + }) { + let matched_test_item = test_items.iter().find(|item| item.id == executed_test_id); + let lnum = m.get(3).unwrap().as_str().parse::().unwrap() - 1; let col = m.get(4).unwrap().as_str().parse::().unwrap() - 1; let mut next_i = i + 1; @@ -309,10 +325,42 @@ pub fn parse_cargo_diagnostics( character: MAX_CHAR_LENGTH, }, }, - message, + message: message.clone(), severity: Some(DiagnosticSeverity::ERROR), ..Diagnostic::default() }; + + // if the test item is matched, + // add a diagnostic to the beginning of the test item + // in order to show which test failed. + // If this code does not exist, only panicked positions are shown + if let Some(test_item) = matched_test_item { + let message = format!( + "`{}` failed at {relative_file_path}:{lnum}:{col}\nMessage:\n{message}", + test_item.name + ); + let lnum = test_item.start_position.start.line; + let col = test_item.start_position.start.character; + let diagnostic = Diagnostic { + range: Range { + start: Position { + line: lnum, + character: col, + }, + end: Position { + line: lnum, + character: MAX_CHAR_LENGTH, + }, + }, + message, + severity: Some(DiagnosticSeverity::ERROR), + ..Diagnostic::default() + }; + result_map + .entry(file_path.to_string()) + .or_default() + .push(diagnostic); + } result_map .entry(file_path.to_string()) .or_default() diff --git a/demo/rust/src/lib.rs b/demo/rust/src/lib.rs index 60b0199..c3b5f5f 100644 --- a/demo/rust/src/lib.rs +++ b/demo/rust/src/lib.rs @@ -53,4 +53,13 @@ mod tests { } } } + + fn p() { + panic!("test failed"); + } + + #[test] + fn test_panic() { + p(); + } } From c511c02107ce4a0836565d889da4389ec1a15e9b Mon Sep 17 00:00:00 2001 From: kbwo Date: Mon, 2 Dec 2024 19:39:23 +0900 Subject: [PATCH 112/139] chore: update error message --- src/server.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/server.rs b/src/server.rs index bd60bab..bd5dec9 100644 --- a/src/server.rs +++ b/src/server.rs @@ -317,8 +317,7 @@ impl TestingLS { .map_err(|err| LSError::Adapter(err.to_string()))?; let Output { stdout, stderr, .. } = output; if !stderr.is_empty() { - let message = - "Cannot run test command: \n".to_string() + &String::from_utf8(stderr).unwrap(); + let message = "Error occurred when running test via adapter.\nCheck adapter log or run tests manually".to_string(); let message_type = MessageType::ERROR; let params: ShowMessageParams = ShowMessageParams { typ: message_type, From d98623211d345a4d14d910d63d8ed012fc80a22f Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 17:28:06 +0900 Subject: [PATCH 113/139] docs: update README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index da96906..74ae301 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # testing-language-server +⚠️ **IMPORTANT NOTICE** +This project is under active development and may introduce breaking changes. If you encounter any issues, please make sure to update to the latest version before reporting bugs. + General purpose LSP server that integrate with testing. The language server is characterized by portability and extensibility. From b205f9580d58f3d601ea2e835c477f0aebccc9f1 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 22:47:12 +0900 Subject: [PATCH 114/139] feat: update interface of `run-file-test` result --- src/server.rs | 5 +++-- src/spec.rs | 12 +++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/server.rs b/src/server.rs index bd5dec9..0b803e3 100644 --- a/src/server.rs +++ b/src/server.rs @@ -337,10 +337,11 @@ impl TestingLS { Ok(res) => { for target_file in paths { let diagnostics_for_file: Vec = res + .data .clone() .into_iter() - .filter(|RunFileTestResultItem { path, .. }| path == target_file) - .flat_map(|RunFileTestResultItem { diagnostics, .. }| diagnostics) + .filter(|FileDiagnostics { path, .. }| path == target_file) + .flat_map(|FileDiagnostics { diagnostics, .. }| diagnostics) .collect(); let uri = Url::from_file_path(target_file.replace("file://", "")).unwrap(); diagnostics.push((uri.to_string(), diagnostics_for_file)); diff --git a/src/spec.rs b/src/spec.rs index 06d2f6f..54c8dd5 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -1,6 +1,7 @@ use clap::Parser; use lsp_types::Diagnostic; use lsp_types::Range; +use lsp_types::ShowMessageParams; use serde::Deserialize; use serde::Serialize; use std::collections::HashMap; @@ -80,14 +81,19 @@ pub struct AdapterConfiguration { /// Result of ` detect-workspace` pub type DetectWorkspaceResult = HashMap>; -/// Result of ` run-file-test` #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] -pub struct RunFileTestResultItem { +pub struct FileDiagnostics { pub path: String, pub diagnostics: Vec, } -pub type RunFileTestResult = Vec; +/// Result of ` run-file-test` +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] +pub struct RunFileTestResult { + pub data: Vec, + #[serde(default)] + pub messages: Vec, +} #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct TestItem { From bb4d9687df1bdc6a6267052d3547229ee06c5a6b Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 22:55:07 +0900 Subject: [PATCH 115/139] feat: update interface of `discover` result --- src/server.rs | 7 +++++-- src/spec.rs | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/server.rs b/src/server.rs index 0b803e3..b54ba1b 100644 --- a/src/server.rs +++ b/src/server.rs @@ -13,6 +13,7 @@ use std::path::Path; use std::path::PathBuf; use std::process::Command; use std::process::Output; +use testing_language_server::spec::DiscoverResult; const TOML_FILE_NAME: &str = ".testingls.toml"; @@ -413,7 +414,7 @@ impl TestingLS { #[allow(clippy::for_kv_map)] pub fn discover_file(&self, path: &str) -> Result { let target_paths = vec![path.to_string()]; - let mut result: DiscoverResult = vec![]; + let mut result: DiscoverResult = DiscoverResult { data: vec![] }; for WorkspaceAnalysis { adapter_config: adapter, workspaces, @@ -423,7 +424,9 @@ impl TestingLS { if !paths.contains(&path.to_string()) { continue; } - result.extend(self.discover(adapter, &target_paths)?); + result + .data + .extend(self.discover(adapter, &target_paths)?.data); } } Ok(result) diff --git a/src/spec.rs b/src/spec.rs index 54c8dd5..5db25dc 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -110,4 +110,7 @@ pub struct DiscoverResultItem { } /// Result of ` discover` -pub type DiscoverResult = Vec; +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct DiscoverResult { + pub data: Vec, +} From 99cd28c5409c4c336831a2334731c6b1364d838f Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 23:04:15 +0900 Subject: [PATCH 116/139] feat: update interface of `detect-workspace` result --- src/server.rs | 17 +++++++++++------ src/spec.rs | 9 ++++++--- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/server.rs b/src/server.rs index b54ba1b..06bd5a8 100644 --- a/src/server.rs +++ b/src/server.rs @@ -203,15 +203,18 @@ impl TestingLS { .unwrap() .to_string(); let target_paths = workspace + .data .into_iter() .flat_map(|kv| kv.1) .collect::>(); HashMap::from([(workspace_dir, target_paths)]) } else { - workspace + workspace.data }; - self.workspaces_cache - .push(WorkspaceAnalysis::new(adapter, workspace)) + self.workspaces_cache.push(WorkspaceAnalysis::new( + adapter, + DetectWorkspaceResult { data: workspace }, + )) } tracing::info!("workspaces_cache={:#?}", self.workspaces_cache); send_stdout(&json!({ @@ -238,7 +241,7 @@ impl TestingLS { adapter_config: adapter, workspaces, }| { - workspaces.iter().for_each(|(workspace, paths)| { + workspaces.data.iter().for_each(|(workspace, paths)| { let _ = self.diagnose(adapter, workspace, paths); }) }, @@ -254,6 +257,7 @@ impl TestingLS { let exclude = &cache.adapter_config.exclude; if cache .workspaces + .data .iter() .any(|(_, workspace)| workspace.contains(&path.to_string())) { @@ -281,7 +285,7 @@ impl TestingLS { adapter_config: adapter, workspaces, }| { - for (workspace, paths) in workspaces.iter() { + for (workspace, paths) in workspaces.data.iter() { if !paths.contains(&path.to_string()) { continue; } @@ -420,7 +424,7 @@ impl TestingLS { workspaces, } in &self.workspaces_cache { - for (_, paths) in workspaces.iter() { + for (_, paths) in workspaces.data.iter() { if !paths.contains(&path.to_string()) { continue; } @@ -537,6 +541,7 @@ mod tests { assert!(adapter_command_path.contains("target/debug/testing-ls-adapter")); workspace_analysis .workspaces + .data .iter() .for_each(|(workspace, paths)| { assert_eq!(workspace, abs_path_of_demo.to_str().unwrap()); diff --git a/src/spec.rs b/src/spec.rs index 5db25dc..cab2e2a 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -79,7 +79,10 @@ pub struct AdapterConfiguration { } /// Result of ` detect-workspace` -pub type DetectWorkspaceResult = HashMap>; +#[derive(Debug, Serialize, Clone, Deserialize)] +pub struct DetectWorkspaceResult { + pub data: HashMap>, +} #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct FileDiagnostics { @@ -104,7 +107,7 @@ pub struct TestItem { } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] -pub struct DiscoverResultItem { +pub struct FoundFileTests { pub path: String, pub tests: Vec, } @@ -112,5 +115,5 @@ pub struct DiscoverResultItem { /// Result of ` discover` #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct DiscoverResult { - pub data: Vec, + pub data: Vec, } From b28ba1aee08929fcbcddac601440c6e238f175de Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 23:15:02 +0900 Subject: [PATCH 117/139] chore: v0.1.8 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b06e43..7963a5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,6 +724,8 @@ dependencies = [ [[package]] name = "testing-language-server" version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fae6ce9cb290e80814d1796e4207a0a0dc21c216807136d48b68c0f27be29b9" dependencies = [ "anyhow", "chrono", @@ -747,9 +749,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fae6ce9cb290e80814d1796e4207a0a0dc21c216807136d48b68c0f27be29b9" +version = "0.1.8" dependencies = [ "anyhow", "chrono", @@ -783,7 +783,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "testing-language-server 0.1.7", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index af93e9c..2ae8a1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.7" +version = "0.1.8" edition = "2021" description = "LSP server for testing" license = "MIT" From 1fae0f701af507c6e5bb88ee619cc7970a022021 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 23:23:18 +0900 Subject: [PATCH 118/139] chore(adapter): update adapter dependency --- Cargo.lock | 8 ++++---- crates/adapter/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7963a5f..a8e030a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -723,9 +723,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fae6ce9cb290e80814d1796e4207a0a0dc21c216807136d48b68c0f27be29b9" +version = "0.1.8" dependencies = [ "anyhow", "chrono", @@ -750,6 +748,8 @@ dependencies = [ [[package]] name = "testing-language-server" version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f62894ce27874e8a8bde477d8036fe80acae38a20852f9019d3c881899cc874a" dependencies = [ "anyhow", "chrono", @@ -783,7 +783,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.1.7", + "testing-language-server 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 5148bd1..2c48aad 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -testing-language-server = "0.1.7" +testing-language-server = "0.1.8" lsp-types = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } From 2fa914973f5ad770d95b2b7f8602b639ce399ad2 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 22:48:02 +0900 Subject: [PATCH 119/139] feat(adapter): use new interface of `run-file-test` --- crates/adapter/src/runner/cargo_nextest.rs | 39 ++++++++++++---------- crates/adapter/src/runner/cargo_test.rs | 39 ++++++++++++---------- crates/adapter/src/runner/deno.rs | 15 +++++---- crates/adapter/src/runner/go.rs | 15 +++++---- crates/adapter/src/runner/jest.rs | 15 +++++---- crates/adapter/src/runner/node_test.rs | 14 +++++--- crates/adapter/src/runner/phpunit.rs | 14 +++++--- crates/adapter/src/runner/util.rs | 24 +++++++++---- crates/adapter/src/runner/vitest.rs | 15 +++++---- 9 files changed, 112 insertions(+), 78 deletions(-) diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index 202a2b9..65b8c96 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -106,7 +106,7 @@ impl Runner for CargoNextestRunner { #[cfg(test)] mod tests { use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; - use testing_language_server::spec::{RunFileTestResultItem, TestItem}; + use testing_language_server::spec::{FileDiagnostics, TestItem}; use crate::runner::util::MAX_CHAR_LENGTH; @@ -171,24 +171,27 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace assert_eq!( diagnostics, - vec![RunFileTestResultItem { - path: file_paths.first().unwrap().to_owned(), - diagnostics: vec![Diagnostic { - range: Range { - start: Position { - line: 85, - character: 63 + RunFileTestResult { + data: vec![FileDiagnostics { + path: file_paths.first().unwrap().to_owned(), + diagnostics: vec![Diagnostic { + range: Range { + start: Position { + line: 85, + character: 63 + }, + end: Position { + line: 85, + character: MAX_CHAR_LENGTH + } }, - end: Position { - line: 85, - character: MAX_CHAR_LENGTH - } - }, - message: message.to_string(), - severity: Some(DiagnosticSeverity::ERROR), - ..Diagnostic::default() - }] - }] + message: message.to_string(), + severity: Some(DiagnosticSeverity::ERROR), + ..Diagnostic::default() + }] + }], + messages: vec!() + } ) } diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index bea62bd..e37e3e9 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -101,7 +101,7 @@ impl Runner for CargoTestRunner { #[cfg(test)] mod tests { use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; - use testing_language_server::spec::RunFileTestResultItem; + use testing_language_server::spec::FileDiagnostics; use crate::runner::util::MAX_CHAR_LENGTH; @@ -166,24 +166,27 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace assert_eq!( diagnostics, - vec![RunFileTestResultItem { - path: file_paths.first().unwrap().to_owned(), - diagnostics: vec![Diagnostic { - range: Range { - start: Position { - line: 85, - character: 63 + RunFileTestResult { + data: vec![FileDiagnostics { + path: file_paths.first().unwrap().to_owned(), + diagnostics: vec![Diagnostic { + range: Range { + start: Position { + line: 85, + character: 63 + }, + end: Position { + line: 85, + character: MAX_CHAR_LENGTH + } }, - end: Position { - line: 85, - character: MAX_CHAR_LENGTH - } - }, - message: message.to_string(), - severity: Some(DiagnosticSeverity::ERROR), - ..Diagnostic::default() - }] - }] + message: message.to_string(), + severity: Some(DiagnosticSeverity::ERROR), + ..Diagnostic::default() + }] + }], + messages: vec![] + } ) } diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index d85fe5b..dd145ad 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -14,8 +14,8 @@ use testing_language_server::error::LSError; use testing_language_server::spec::DetectWorkspaceResult; use testing_language_server::spec::DiscoverResult; use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::FileDiagnostics; use testing_language_server::spec::RunFileTestResult; -use testing_language_server::spec::RunFileTestResultItem; use testing_language_server::spec::TestItem; use crate::model::Runner; @@ -89,10 +89,13 @@ fn parse_diagnostics( message += line; } } - Ok(result_map - .into_iter() - .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) - .collect()) + Ok(RunFileTestResult { + data: result_map + .into_iter() + .map(|(path, diagnostics)| FileDiagnostics { path, diagnostics }) + .collect(), + messages: vec![], + }) } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { @@ -229,7 +232,7 @@ mod tests { let target_file_path = "/home/demo/test/dneo/main_test.ts"; let diagnostics = parse_diagnostics(&test_result, workspace, &[target_file_path.to_string()]).unwrap(); - assert_eq!(diagnostics.len(), 1); + assert_eq!(diagnostics.data.len(), 1); } #[test] diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 6ba3a1d..3acb651 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -14,8 +14,8 @@ use std::str::FromStr; use testing_language_server::error::LSError; use testing_language_server::spec::DiscoverResult; use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::FileDiagnostics; use testing_language_server::spec::RunFileTestResult; -use testing_language_server::spec::RunFileTestResultItem; use testing_language_server::spec::TestItem; use super::util::detect_workspaces_from_file_list; @@ -130,10 +130,13 @@ fn parse_diagnostics( } } - Ok(result_map - .into_iter() - .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) - .collect()) + Ok(RunFileTestResult { + data: result_map + .into_iter() + .map(|(path, diagnostics)| FileDiagnostics { path, diagnostics }) + .collect(), + messages: vec![], + }) } fn discover(file_path: &str) -> Result, LSError> { @@ -305,7 +308,7 @@ mod tests { let target_file_path = "/home/demo/test/go/src/test/cases_test.go"; let result = parse_diagnostics(&contents, workspace, &[target_file_path.to_string()]).unwrap(); - let result = result.first().unwrap(); + let result = result.data.first().unwrap(); assert_eq!(result.path, target_file_path); let diagnostic = result.diagnostics.first().unwrap(); assert_eq!(diagnostic.range.start.line, 30); diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index f8b2a92..c575388 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -9,8 +9,8 @@ use testing_language_server::error::LSError; use testing_language_server::spec::DetectWorkspaceResult; use testing_language_server::spec::DiscoverResult; use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::FileDiagnostics; use testing_language_server::spec::RunFileTestResult; -use testing_language_server::spec::RunFileTestResultItem; use testing_language_server::spec::TestItem; use crate::model::Runner; @@ -67,10 +67,13 @@ fn parse_diagnostics( }) } } - Ok(result_map - .into_iter() - .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) - .collect()) + Ok(RunFileTestResult { + data: result_map + .into_iter() + .map(|(path, diagnostics)| FileDiagnostics { path, diagnostics }) + .collect(), + messages: vec![], + }) } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { @@ -229,7 +232,7 @@ mod tests { ], ) .unwrap(); - assert_eq!(diagnostics.len(), 2); + assert_eq!(diagnostics.data.len(), 2); } #[test] diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs index 117ad61..060b096 100644 --- a/crates/adapter/src/runner/node_test.rs +++ b/crates/adapter/src/runner/node_test.rs @@ -4,8 +4,8 @@ use regex::Regex; use testing_language_server::{ error::LSError, spec::{ - DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, RunFileTestResult, - RunFileTestResultItem, TestItem, + DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, FileDiagnostics, + RunFileTestResult, TestItem, }, }; use xml::{reader::XmlEvent, ParserConfig}; @@ -194,14 +194,18 @@ impl Runner for NodeTestRunner { } let stdout = String::from_utf8(stdout).unwrap(); let result_from_xml = get_result_from_xml(&stdout, &file_paths)?; - let diagnostics: RunFileTestResult = result_from_xml + let result_item: Vec = result_from_xml .into_iter() .map(|result_from_xml| { - let result_item: RunFileTestResultItem = result_from_xml.into(); + let result_item: FileDiagnostics = result_from_xml.into(); result_item }) .collect(); - send_stdout(&diagnostics)?; + let result = RunFileTestResult { + data: result_item, + messages: vec![], + }; + send_stdout(&result)?; Ok(()) } diff --git a/crates/adapter/src/runner/phpunit.rs b/crates/adapter/src/runner/phpunit.rs index 0d765d8..df25c59 100644 --- a/crates/adapter/src/runner/phpunit.rs +++ b/crates/adapter/src/runner/phpunit.rs @@ -3,8 +3,8 @@ use std::io::BufReader; use std::process::Output; use testing_language_server::error::LSError; use testing_language_server::spec::{ - DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, RunFileTestResult, - RunFileTestResultItem, TestItem, + DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, FileDiagnostics, RunFileTestResult, + TestItem, }; use xml::reader::{ParserConfig, XmlEvent}; @@ -177,14 +177,18 @@ impl Runner for PhpunitRunner { return Err(LSError::Adapter(String::from_utf8(stderr).unwrap())); } let result_from_xml = get_result_from_xml(log_path.to_str().unwrap())?; - let diagnostics: RunFileTestResult = result_from_xml + let result_item: Vec = result_from_xml .into_iter() .map(|result_from_xml| { - let result_item: RunFileTestResultItem = result_from_xml.into(); + let result_item: FileDiagnostics = result_from_xml.into(); result_item }) .collect(); - send_stdout(&diagnostics)?; + let result = RunFileTestResult { + data: result_item, + messages: vec![], + }; + send_stdout(&result)?; Ok(()) } diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index b598214..1cbb1f9 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -8,7 +8,7 @@ use std::sync::LazyLock; use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; use regex::Regex; use serde::Serialize; -use testing_language_server::spec::{RunFileTestResultItem, TestItem}; +use testing_language_server::spec::{FileDiagnostics, TestItem}; use testing_language_server::{error::LSError, spec::RunFileTestResult}; use tree_sitter::{Language, Point, Query, QueryCursor}; @@ -30,9 +30,10 @@ pub struct ResultFromXml { pub col: u32, } -impl Into for ResultFromXml { - fn into(self) -> RunFileTestResultItem { - RunFileTestResultItem { +#[allow(clippy::from_over_into)] +impl Into for ResultFromXml { + fn into(self) -> FileDiagnostics { + FileDiagnostics { path: self.path, diagnostics: vec![Diagnostic { message: self.message, @@ -371,10 +372,19 @@ pub fn parse_cargo_diagnostics( } } - result_map + let no_diagnostic = result_map + .values() + .all(|diagnostics| !diagnostics.is_empty()); + + let data = result_map .into_iter() - .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) - .collect() + .map(|(path, diagnostics)| FileDiagnostics { path, diagnostics }) + .collect(); + + RunFileTestResult { + data, + messages: vec![], + } } /// remove this function because duplicate implementation diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 11c18f7..474cd18 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -7,9 +7,7 @@ use lsp_types::{Diagnostic, DiagnosticSeverity}; use serde_json::Value; use testing_language_server::{ error::LSError, - spec::{ - DiscoverResult, DiscoverResultItem, RunFileTestResult, RunFileTestResultItem, TestItem, - }, + spec::{DiscoverResult, DiscoverResultItem, FileDiagnostics, RunFileTestResult, TestItem}, }; use crate::model::Runner; @@ -124,10 +122,13 @@ fn parse_diagnostics( }) } } - Ok(result_map - .into_iter() - .map(|(path, diagnostics)| RunFileTestResultItem { path, diagnostics }) - .collect()) + Ok(RunFileTestResult { + data: result_map + .into_iter() + .map(|(path, diagnostics)| FileDiagnostics { path, diagnostics }) + .collect(), + messages: vec![], + }) } impl Runner for VitestRunner { From df0631a6d63ee6fb558d1198f63306c06db7d0ca Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 22:55:24 +0900 Subject: [PATCH 120/139] feat(adapter): use new interface of `discover` --- crates/adapter/src/runner/cargo_nextest.rs | 4 ++-- crates/adapter/src/runner/cargo_test.rs | 4 ++-- crates/adapter/src/runner/deno.rs | 4 ++-- crates/adapter/src/runner/go.rs | 4 ++-- crates/adapter/src/runner/jest.rs | 4 ++-- crates/adapter/src/runner/node_test.rs | 4 ++-- crates/adapter/src/runner/phpunit.rs | 4 ++-- crates/adapter/src/runner/vitest.rs | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index 65b8c96..a432c7f 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -28,11 +28,11 @@ impl Runner for CargoNextestRunner { #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; - let mut discover_results: DiscoverResult = vec![]; + let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { let tests = discover_rust_tests(&file_path)?; - discover_results.push(DiscoverResultItem { + discover_results.data.push(DiscoverResultItem { tests, path: file_path, }); diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index e37e3e9..49cfbba 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -28,11 +28,11 @@ impl Runner for CargoTestRunner { #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; - let mut discover_results: DiscoverResult = vec![]; + let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { let tests = discover_rust_tests(&file_path)?; - discover_results.push(DiscoverResultItem { + discover_results.data.push(DiscoverResultItem { tests, path: file_path, }); diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index dd145ad..2240cbb 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -164,9 +164,9 @@ impl Runner for DenoRunner { #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; - let mut discover_results: DiscoverResult = vec![]; + let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { - discover_results.push(DiscoverResultItem { + discover_results.data.push(DiscoverResultItem { tests: discover(&file_path)?, path: file_path, }) diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 3acb651..1807cde 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -235,11 +235,11 @@ impl Runner for GoTestRunner { args: testing_language_server::spec::DiscoverArgs, ) -> Result<(), testing_language_server::error::LSError> { let file_paths = args.file_paths; - let mut discover_results: DiscoverResult = vec![]; + let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { let tests = discover(&file_path)?; - discover_results.push(DiscoverResultItem { + discover_results.data.push(DiscoverResultItem { tests, path: file_path, }); diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index c575388..7a99fc0 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -162,9 +162,9 @@ impl Runner for JestRunner { #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; - let mut discover_results: DiscoverResult = vec![]; + let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { - discover_results.push(DiscoverResultItem { + discover_results.data.push(DiscoverResultItem { tests: discover(&file_path)?, path: file_path, }) diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs index 060b096..cfef3bf 100644 --- a/crates/adapter/src/runner/node_test.rs +++ b/crates/adapter/src/runner/node_test.rs @@ -162,9 +162,9 @@ impl Runner for NodeTestRunner { #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; - let mut discover_results: DiscoverResult = vec![]; + let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { - discover_results.push(DiscoverResultItem { + discover_results.data.push(DiscoverResultItem { tests: discover(&file_path)?, path: file_path, }) diff --git a/crates/adapter/src/runner/phpunit.rs b/crates/adapter/src/runner/phpunit.rs index df25c59..c250e09 100644 --- a/crates/adapter/src/runner/phpunit.rs +++ b/crates/adapter/src/runner/phpunit.rs @@ -125,9 +125,9 @@ impl Runner for PhpunitRunner { #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; - let mut discover_results: DiscoverResult = vec![]; + let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { - discover_results.push(DiscoverResultItem { + discover_results.data.push(DiscoverResultItem { tests: discover(&file_path)?, path: file_path, }) diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 474cd18..496991e 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -135,11 +135,11 @@ impl Runner for VitestRunner { #[tracing::instrument(skip(self))] fn discover(&self, args: testing_language_server::spec::DiscoverArgs) -> Result<(), LSError> { let file_paths = args.file_paths; - let mut discover_results: DiscoverResult = vec![]; + let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { let tests = discover(&file_path)?; - discover_results.push(DiscoverResultItem { + discover_results.data.push(DiscoverResultItem { tests, path: file_path, }); From 787e92fe873edbe7419884d54c00d33ffd5802dc Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 23:04:55 +0900 Subject: [PATCH 121/139] feat(adapter): use new interface of `detect-workspace` --- crates/adapter/src/runner/cargo_nextest.rs | 16 ++++++++++------ crates/adapter/src/runner/cargo_test.rs | 16 ++++++++++------ crates/adapter/src/runner/deno.rs | 12 +++++++----- crates/adapter/src/runner/go.rs | 4 ++-- crates/adapter/src/runner/jest.rs | 12 +++++++----- crates/adapter/src/runner/node_test.rs | 11 ++++++----- crates/adapter/src/runner/phpunit.rs | 8 +++++--- crates/adapter/src/runner/vitest.rs | 4 ++-- 8 files changed, 49 insertions(+), 34 deletions(-) diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index a432c7f..8948938 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -7,7 +7,7 @@ use testing_language_server::spec::DetectWorkspaceResult; use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::DiscoverResult; -use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::FoundFileTests; use testing_language_server::spec::TestItem; use crate::model::Runner; @@ -18,7 +18,9 @@ use super::util::parse_cargo_diagnostics; use super::util::write_result_log; fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { - detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]) + DetectWorkspaceResult { + data: detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]), + } } #[derive(Eq, PartialEq, Hash, Debug)] @@ -32,7 +34,7 @@ impl Runner for CargoNextestRunner { for file_path in file_paths { let tests = discover_rust_tests(&file_path)?; - discover_results.data.push(DiscoverResultItem { + discover_results.data.push(FoundFileTests { tests, path: file_path, }); @@ -214,8 +216,10 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace .collect(); let workspaces = detect_workspaces(&file_paths); - assert_eq!(workspaces.len(), 2); - assert!(workspaces.contains_key(absolute_path_of_demo.to_str().unwrap())); - assert!(workspaces.contains_key(current_dir.to_str().unwrap())); + assert_eq!(workspaces.data.len(), 2); + assert!(workspaces + .data + .contains_key(absolute_path_of_demo.to_str().unwrap())); + assert!(workspaces.data.contains_key(current_dir.to_str().unwrap())); } } diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 49cfbba..914862c 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -7,7 +7,7 @@ use testing_language_server::spec::DetectWorkspaceResult; use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::DiscoverResult; -use testing_language_server::spec::DiscoverResultItem; +use testing_language_server::spec::FoundFileTests; use testing_language_server::spec::TestItem; use crate::model::Runner; @@ -18,7 +18,9 @@ use super::util::parse_cargo_diagnostics; use super::util::write_result_log; fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { - detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]) + DetectWorkspaceResult { + data: detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]), + } } #[derive(Eq, PartialEq, Hash, Debug)] @@ -32,7 +34,7 @@ impl Runner for CargoTestRunner { for file_path in file_paths { let tests = discover_rust_tests(&file_path)?; - discover_results.data.push(DiscoverResultItem { + discover_results.data.push(FoundFileTests { tests, path: file_path, }); @@ -209,8 +211,10 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace .collect(); let workspaces = detect_workspaces(&file_paths); - assert_eq!(workspaces.len(), 2); - assert!(workspaces.contains_key(absolute_path_of_demo.to_str().unwrap())); - assert!(workspaces.contains_key(current_dir.to_str().unwrap())); + assert_eq!(workspaces.data.len(), 2); + assert!(workspaces + .data + .contains_key(absolute_path_of_demo.to_str().unwrap())); + assert!(workspaces.data.contains_key(current_dir.to_str().unwrap())); } } diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index 2240cbb..60a6b2e 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -13,8 +13,8 @@ use testing_language_server::error::LSError; use testing_language_server::spec::DetectWorkspaceResult; use testing_language_server::spec::DiscoverResult; -use testing_language_server::spec::DiscoverResultItem; use testing_language_server::spec::FileDiagnostics; +use testing_language_server::spec::FoundFileTests; use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::TestItem; @@ -99,7 +99,9 @@ fn parse_diagnostics( } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - detect_workspaces_from_file_list(&file_paths, &["deno.json".to_string()]) + DetectWorkspaceResult { + data: detect_workspaces_from_file_list(&file_paths, &["deno.json".to_string()]), + } } fn discover(file_path: &str) -> Result, LSError> { @@ -166,7 +168,7 @@ impl Runner for DenoRunner { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { - discover_results.data.push(DiscoverResultItem { + discover_results.data.push(FoundFileTests { tests: discover(&file_path)?, path: file_path, }) @@ -245,8 +247,8 @@ mod tests { .map(|file_path| file_path.to_str().unwrap().to_string()) .collect(); let detect_result = detect_workspaces(file_paths); - assert_eq!(detect_result.len(), 1); - detect_result.iter().for_each(|(workspace, _)| { + assert_eq!(detect_result.data.len(), 1); + detect_result.data.iter().for_each(|(workspace, _)| { assert_eq!(workspace, absolute_path_of_demo.to_str().unwrap()); }); } diff --git a/crates/adapter/src/runner/go.rs b/crates/adapter/src/runner/go.rs index 1807cde..0f89d5a 100644 --- a/crates/adapter/src/runner/go.rs +++ b/crates/adapter/src/runner/go.rs @@ -13,8 +13,8 @@ use std::process::Output; use std::str::FromStr; use testing_language_server::error::LSError; use testing_language_server::spec::DiscoverResult; -use testing_language_server::spec::DiscoverResultItem; use testing_language_server::spec::FileDiagnostics; +use testing_language_server::spec::FoundFileTests; use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::TestItem; @@ -239,7 +239,7 @@ impl Runner for GoTestRunner { for file_path in file_paths { let tests = discover(&file_path)?; - discover_results.data.push(DiscoverResultItem { + discover_results.data.push(FoundFileTests { tests, path: file_path, }); diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index 7a99fc0..b33a4d9 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -8,8 +8,8 @@ use testing_language_server::error::LSError; use testing_language_server::spec::DetectWorkspaceResult; use testing_language_server::spec::DiscoverResult; -use testing_language_server::spec::DiscoverResultItem; use testing_language_server::spec::FileDiagnostics; +use testing_language_server::spec::FoundFileTests; use testing_language_server::spec::RunFileTestResult; use testing_language_server::spec::TestItem; @@ -77,7 +77,9 @@ fn parse_diagnostics( } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]) + DetectWorkspaceResult { + data: detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]), + } } fn discover(file_path: &str) -> Result, LSError> { @@ -164,7 +166,7 @@ impl Runner for JestRunner { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { - discover_results.data.push(DiscoverResultItem { + discover_results.data.push(FoundFileTests { tests: discover(&file_path)?, path: file_path, }) @@ -245,8 +247,8 @@ mod tests { .map(|file_path| file_path.to_str().unwrap().to_string()) .collect(); let detect_result = detect_workspaces(file_paths); - assert_eq!(detect_result.len(), 1); - detect_result.iter().for_each(|(workspace, _)| { + assert_eq!(detect_result.data.len(), 1); + detect_result.data.iter().for_each(|(workspace, _)| { assert_eq!(workspace, absolute_path_of_demo.to_str().unwrap()); }); } diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs index cfef3bf..6551361 100644 --- a/crates/adapter/src/runner/node_test.rs +++ b/crates/adapter/src/runner/node_test.rs @@ -4,8 +4,8 @@ use regex::Regex; use testing_language_server::{ error::LSError, spec::{ - DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, FileDiagnostics, - RunFileTestResult, TestItem, + DetectWorkspaceResult, DiscoverResult, FileDiagnostics, FoundFileTests, RunFileTestResult, + TestItem, }, }; use xml::{reader::XmlEvent, ParserConfig}; @@ -164,7 +164,7 @@ impl Runner for NodeTestRunner { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { - discover_results.data.push(DiscoverResultItem { + discover_results.data.push(FoundFileTests { tests: discover(&file_path)?, path: file_path, }) @@ -215,8 +215,9 @@ impl Runner for NodeTestRunner { args: testing_language_server::spec::DetectWorkspaceArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; - let detect_result: DetectWorkspaceResult = - detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]); + let detect_result: DetectWorkspaceResult = DetectWorkspaceResult { + data: detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]), + }; send_stdout(&detect_result)?; Ok(()) } diff --git a/crates/adapter/src/runner/phpunit.rs b/crates/adapter/src/runner/phpunit.rs index c250e09..ca03bcf 100644 --- a/crates/adapter/src/runner/phpunit.rs +++ b/crates/adapter/src/runner/phpunit.rs @@ -3,7 +3,7 @@ use std::io::BufReader; use std::process::Output; use testing_language_server::error::LSError; use testing_language_server::spec::{ - DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, FileDiagnostics, RunFileTestResult, + DetectWorkspaceResult, DiscoverResult, FileDiagnostics, FoundFileTests, RunFileTestResult, TestItem, }; use xml::reader::{ParserConfig, XmlEvent}; @@ -16,7 +16,9 @@ use super::util::{ }; fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - detect_workspaces_from_file_list(&file_paths, &["composer.json".to_string()]) + DetectWorkspaceResult { + data: detect_workspaces_from_file_list(&file_paths, &["composer.json".to_string()]), + } } fn get_result_from_characters(characters: &str) -> Result { @@ -127,7 +129,7 @@ impl Runner for PhpunitRunner { let file_paths = args.file_paths; let mut discover_results: DiscoverResult = DiscoverResult { data: vec![] }; for file_path in file_paths { - discover_results.data.push(DiscoverResultItem { + discover_results.data.push(FoundFileTests { tests: discover(&file_path)?, path: file_path, }) diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 496991e..3cab43d 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -7,7 +7,7 @@ use lsp_types::{Diagnostic, DiagnosticSeverity}; use serde_json::Value; use testing_language_server::{ error::LSError, - spec::{DiscoverResult, DiscoverResultItem, FileDiagnostics, RunFileTestResult, TestItem}, + spec::{DiscoverResult, FileDiagnostics, FoundFileTests, RunFileTestResult, TestItem}, }; use crate::model::Runner; @@ -139,7 +139,7 @@ impl Runner for VitestRunner { for file_path in file_paths { let tests = discover(&file_path)?; - discover_results.data.push(DiscoverResultItem { + discover_results.data.push(FoundFileTests { tests, path: file_path, }); From 1df30762599071feaedcdd027d266ec61a3b37e7 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 23:24:54 +0900 Subject: [PATCH 122/139] refactor: delete unused variable --- crates/adapter/src/runner/util.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index 1cbb1f9..d086e6f 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -372,10 +372,6 @@ pub fn parse_cargo_diagnostics( } } - let no_diagnostic = result_map - .values() - .all(|diagnostics| !diagnostics.is_empty()); - let data = result_map .into_iter() .map(|(path, diagnostics)| FileDiagnostics { path, diagnostics }) From 6c75bbbd47e37ffb991da21e84689b85209eac8b Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 7 Dec 2024 23:25:23 +0900 Subject: [PATCH 123/139] chore(adapter): v0.1.0 --- Cargo.lock | 2 +- crates/adapter/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8e030a..24a09e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -773,7 +773,7 @@ dependencies = [ [[package]] name = "testing-ls-adapter" -version = "0.0.11" +version = "0.1.0" dependencies = [ "anyhow", "clap", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 2c48aad..5c43720 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.0.11" +version = "0.1.0" edition = "2021" description = "testing-language-server adapter" license = "MIT" From 942f0b4ed138eda1db086a6bd3ad0de98ba43da9 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 24 Dec 2024 17:11:06 +0900 Subject: [PATCH 124/139] fix(adapter): return valid json type to server --- crates/adapter/src/log.rs | 4 ++-- crates/adapter/src/runner/cargo_nextest.rs | 4 +--- crates/adapter/src/runner/cargo_test.rs | 4 +--- crates/adapter/src/runner/deno.rs | 4 +--- crates/adapter/src/runner/jest.rs | 4 +--- crates/adapter/src/runner/node_test.rs | 5 ++--- crates/adapter/src/runner/phpunit.rs | 4 +--- crates/adapter/src/runner/util.rs | 6 +++--- 8 files changed, 12 insertions(+), 23 deletions(-) diff --git a/crates/adapter/src/log.rs b/crates/adapter/src/log.rs index 6a17a5a..32ea729 100644 --- a/crates/adapter/src/log.rs +++ b/crates/adapter/src/log.rs @@ -8,8 +8,8 @@ pub struct Log; impl Log { fn log_dir() -> PathBuf { let home_dir = dirs::home_dir().unwrap(); - let log_path = home_dir.join(".config/testing_language_server/adapter/logs"); - log_path + + home_dir.join(".config/testing_language_server/adapter/logs") } pub fn init() -> Result { diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index 8948938..c6d1780 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -18,9 +18,7 @@ use super::util::parse_cargo_diagnostics; use super::util::write_result_log; fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { - DetectWorkspaceResult { - data: detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]), - } + detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]) } #[derive(Eq, PartialEq, Hash, Debug)] diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index 914862c..e66eaec 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -18,9 +18,7 @@ use super::util::parse_cargo_diagnostics; use super::util::write_result_log; fn detect_workspaces(file_paths: &[String]) -> DetectWorkspaceResult { - DetectWorkspaceResult { - data: detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]), - } + detect_workspaces_from_file_list(file_paths, &["Cargo.toml".to_string()]) } #[derive(Eq, PartialEq, Hash, Debug)] diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index 60a6b2e..270d61a 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -99,9 +99,7 @@ fn parse_diagnostics( } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - DetectWorkspaceResult { - data: detect_workspaces_from_file_list(&file_paths, &["deno.json".to_string()]), - } + detect_workspaces_from_file_list(&file_paths, &["deno.json".to_string()]) } fn discover(file_path: &str) -> Result, LSError> { diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index b33a4d9..e11c269 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -77,9 +77,7 @@ fn parse_diagnostics( } fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - DetectWorkspaceResult { - data: detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]), - } + detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]) } fn discover(file_path: &str) -> Result, LSError> { diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs index 6551361..81b63ad 100644 --- a/crates/adapter/src/runner/node_test.rs +++ b/crates/adapter/src/runner/node_test.rs @@ -215,9 +215,8 @@ impl Runner for NodeTestRunner { args: testing_language_server::spec::DetectWorkspaceArgs, ) -> Result<(), LSError> { let file_paths = args.file_paths; - let detect_result: DetectWorkspaceResult = DetectWorkspaceResult { - data: detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]), - }; + let detect_result: DetectWorkspaceResult = + detect_workspaces_from_file_list(&file_paths, &["package.json".to_string()]); send_stdout(&detect_result)?; Ok(()) } diff --git a/crates/adapter/src/runner/phpunit.rs b/crates/adapter/src/runner/phpunit.rs index ca03bcf..dcca31f 100644 --- a/crates/adapter/src/runner/phpunit.rs +++ b/crates/adapter/src/runner/phpunit.rs @@ -16,9 +16,7 @@ use super::util::{ }; fn detect_workspaces(file_paths: Vec) -> DetectWorkspaceResult { - DetectWorkspaceResult { - data: detect_workspaces_from_file_list(&file_paths, &["composer.json".to_string()]), - } + detect_workspaces_from_file_list(&file_paths, &["composer.json".to_string()]) } fn get_result_from_characters(characters: &str) -> Result { diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index d086e6f..ca540de 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -8,7 +8,7 @@ use std::sync::LazyLock; use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; use regex::Regex; use serde::Serialize; -use testing_language_server::spec::{FileDiagnostics, TestItem}; +use testing_language_server::spec::{DetectWorkspaceResult, FileDiagnostics, TestItem}; use testing_language_server::{error::LSError, spec::RunFileTestResult}; use tree_sitter::{Language, Point, Query, QueryCursor}; @@ -74,7 +74,7 @@ fn detect_workspace_from_file(file_path: PathBuf, file_names: &[String]) -> Opti pub fn detect_workspaces_from_file_list( target_file_paths: &[String], file_names: &[String], -) -> HashMap> { +) -> DetectWorkspaceResult { let mut result_map: HashMap> = HashMap::new(); let mut file_paths = target_file_paths.to_vec(); file_paths.sort_by_key(|b| b.len()); @@ -106,7 +106,7 @@ pub fn detect_workspaces_from_file_list( } } } - result_map + DetectWorkspaceResult { data: result_map } } pub fn send_stdout(value: &T) -> Result<(), LSError> From 5a672ddf7105438b82749ec45c17cbed663cbe35 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 24 Dec 2024 17:12:17 +0900 Subject: [PATCH 125/139] chore(adapter): 0.1.1 --- Cargo.lock | 2 +- crates/adapter/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24a09e4..23dedff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -773,7 +773,7 @@ dependencies = [ [[package]] name = "testing-ls-adapter" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "clap", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index 5c43720..e9680d5 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.1.0" +version = "0.1.1" edition = "2021" description = "testing-language-server adapter" license = "MIT" From 42354d8ec543610dc5a6118e34d9e4fee0302e6b Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 24 Dec 2024 17:12:35 +0900 Subject: [PATCH 126/139] refactor(server): fix for clippy --- src/log.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/log.rs b/src/log.rs index 2949f46..8f39f1f 100644 --- a/src/log.rs +++ b/src/log.rs @@ -7,8 +7,8 @@ pub struct Log; impl Log { fn log_dir() -> PathBuf { let home_dir = dirs::home_dir().unwrap(); - let log_path = home_dir.join(".config/testing_language_server/logs"); - log_path + + home_dir.join(".config/testing_language_server/logs") } pub fn init() -> Result { From 833bfbc1b7057926cfcfb665fe2bd9b82641e205 Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 24 Dec 2024 18:23:31 +0900 Subject: [PATCH 127/139] fix: prevent diagnostics to be cleared when :edit in vim --- src/main.rs | 18 +++++++++--------- src/server.rs | 3 +++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index 93ec957..a0b2fb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,7 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { let stdin = io::stdin(); let mut handle = stdin.lock(); handle.read_line(&mut buffer)?; + tracing::info!("DEBUGPRINT[3]: main.rs:42: buffer={:#?}", buffer); if buffer.is_empty() { tracing::warn!("buffer is empty") @@ -74,11 +75,10 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { handle.read_exact(&mut buf).unwrap(); let message = String::from_utf8(buf).unwrap(); - let value: Value = serde_json::from_str(&message)?; - let method = &value["method"].as_str(); - tracing::info!("method={:#?}", method); - let params = &value["params"]; - tracing::info!("params={:#?}", params); + let received_json: Value = serde_json::from_str(&message)?; + tracing::info!("received json={:#?}", received_json); + let method = &received_json["method"].as_str(); + let params = &received_json["params"]; if let Some(method) = method { match *method { @@ -89,11 +89,11 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { } "initialize" => { let initialize_params = InitializeParams::deserialize(params)?; - let id = value["id"].as_i64().unwrap(); + let id = received_json["id"].as_i64().unwrap(); server.initialize(id, initialize_params)?; } "shutdown" => { - let id = value["id"].as_i64().unwrap(); + let id = received_json["id"].as_i64().unwrap(); server.shutdown(id)?; } "exit" => { @@ -125,7 +125,7 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { server.diagnose_workspace()?; } "$/discoverFileTest" => { - let id = value["id"].as_i64().unwrap(); + let id = received_json["id"].as_i64().unwrap(); let uri = extract_uri(params)?; let result = server.discover_file(&uri)?; send_stdout(&json!({ @@ -136,7 +136,7 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { } _ => { // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#responseMessage - let id = value["id"].as_i64(); + let id = received_json["id"].as_i64(); if id.is_some() { send_error( id, diff --git a/src/server.rs b/src/server.rs index 06bd5a8..e5003c4 100644 --- a/src/server.rs +++ b/src/server.rs @@ -128,6 +128,9 @@ impl TestingLS { workspace_diagnostics: true, work_done_progress_options: WorkDoneProgressOptions::default(), })), + text_document_sync: Some(TextDocumentSyncCapability::Kind( + TextDocumentSyncKind::INCREMENTAL, + )), ..ServerCapabilities::default() } } From 5b8862fe5decbab5c7b7d04e0124bddc30e0065a Mon Sep 17 00:00:00 2001 From: kbwo Date: Tue, 24 Dec 2024 18:24:52 +0900 Subject: [PATCH 128/139] chore: v0.1.9 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23dedff..6e279c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,6 +724,8 @@ dependencies = [ [[package]] name = "testing-language-server" version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f62894ce27874e8a8bde477d8036fe80acae38a20852f9019d3c881899cc874a" dependencies = [ "anyhow", "chrono", @@ -747,9 +749,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f62894ce27874e8a8bde477d8036fe80acae38a20852f9019d3c881899cc874a" +version = "0.1.9" dependencies = [ "anyhow", "chrono", @@ -783,7 +783,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "testing-language-server 0.1.8", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 2ae8a1d..39b3ff3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.8" +version = "0.1.9" edition = "2021" description = "LSP server for testing" license = "MIT" From 4df71f69c01b24582fc3be8af756f17eb24d61a5 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 25 Dec 2024 23:31:26 +0900 Subject: [PATCH 129/139] feat: add `path` field to `TestItem` for demand from adapter --- src/spec.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/spec.rs b/src/spec.rs index cab2e2a..816ddd5 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -102,6 +102,11 @@ pub struct RunFileTestResult { pub struct TestItem { pub id: String, pub name: String, + /// Although FoundFileTests also has a `path` field, we keep the `path` field in TestItem + /// because sometimes we need to determine where a TestItem is located on its own + /// Example: In Rust tests, determining which file contains a test from IDs like relative::path::tests::id + /// TODO: Remove FoundFileTests.path once we confirm it's no longer needed + pub path: String, pub start_position: Range, pub end_position: Range, } From a766099b761e586a16a7d5c7a0af9f3ce476efd5 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 25 Dec 2024 23:32:06 +0900 Subject: [PATCH 130/139] chore: v0.1.10 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e279c4..027c433 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -723,9 +723,9 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f62894ce27874e8a8bde477d8036fe80acae38a20852f9019d3c881899cc874a" +checksum = "f00b929d5091ea09e1a4cc4301042727e0f8445431db22944d604c3f31100375" dependencies = [ "anyhow", "chrono", @@ -749,7 +749,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.9" +version = "0.1.10" dependencies = [ "anyhow", "chrono", @@ -783,7 +783,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.1.8", + "testing-language-server 0.1.9", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 39b3ff3..7eb2649 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.9" +version = "0.1.10" edition = "2021" description = "LSP server for testing" license = "MIT" From 855d2c00944150e14cbc0ac84e13f89fda355c45 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 25 Dec 2024 23:34:31 +0900 Subject: [PATCH 131/139] feat(adapter): add `path` field for server v0.1.10 --- crates/adapter/src/runner/cargo_nextest.rs | 1 + crates/adapter/src/runner/cargo_test.rs | 1 + crates/adapter/src/runner/deno.rs | 3 +++ crates/adapter/src/runner/jest.rs | 1 + crates/adapter/src/runner/node_test.rs | 26 ++++++++++++++++++++++ crates/adapter/src/runner/phpunit.rs | 3 +++ crates/adapter/src/runner/util.rs | 22 ++++++++++-------- crates/adapter/src/runner/vitest.rs | 2 ++ 8 files changed, 50 insertions(+), 9 deletions(-) diff --git a/crates/adapter/src/runner/cargo_nextest.rs b/crates/adapter/src/runner/cargo_nextest.rs index c6d1780..3246388 100644 --- a/crates/adapter/src/runner/cargo_nextest.rs +++ b/crates/adapter/src/runner/cargo_nextest.rs @@ -136,6 +136,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace let test_items: Vec = vec![TestItem { id: "rocks::dependency::tests::parse_dependency".to_string(), name: "rocks::dependency::tests::parse_dependency".to_string(), + path: "/home/example/projects/rocks-lib/src/rocks/dependency.rs".to_string(), start_position: Range { start: Position { line: 85, diff --git a/crates/adapter/src/runner/cargo_test.rs b/crates/adapter/src/runner/cargo_test.rs index e66eaec..f855ed4 100644 --- a/crates/adapter/src/runner/cargo_test.rs +++ b/crates/adapter/src/runner/cargo_test.rs @@ -131,6 +131,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace let test_items: Vec = vec![TestItem { id: "rocks::dependency::tests::parse_dependency".to_string(), name: "rocks::dependency::tests::parse_dependency".to_string(), + path: "/home/example/projects/rocks-lib/src/rocks/dependency.rs".to_string(), start_position: Range { start: Position { line: 85, diff --git a/crates/adapter/src/runner/deno.rs b/crates/adapter/src/runner/deno.rs index 270d61a..b56257f 100644 --- a/crates/adapter/src/runner/deno.rs +++ b/crates/adapter/src/runner/deno.rs @@ -263,6 +263,7 @@ mod tests { TestItem { id: String::from("addTest"), name: String::from("addTest"), + path: file_path.to_string(), start_position: Range { start: Position { line: 7, @@ -287,6 +288,7 @@ mod tests { TestItem { id: String::from("fail1"), name: String::from("fail1"), + path: file_path.to_string(), start_position: Range { start: Position { line: 11, @@ -311,6 +313,7 @@ mod tests { TestItem { id: String::from("fail2"), name: String::from("fail2"), + path: file_path.to_string(), start_position: Range { start: Position { line: 15, diff --git a/crates/adapter/src/runner/jest.rs b/crates/adapter/src/runner/jest.rs index e11c269..08452b2 100644 --- a/crates/adapter/src/runner/jest.rs +++ b/crates/adapter/src/runner/jest.rs @@ -261,6 +261,7 @@ mod tests { vec![TestItem { id: String::from("index::fail"), name: String::from("index::fail"), + path: file_path.to_string(), start_position: Range { start: Position { line: 1, diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs index 81b63ad..ebfbf83 100644 --- a/crates/adapter/src/runner/node_test.rs +++ b/crates/adapter/src/runner/node_test.rs @@ -270,6 +270,7 @@ mod tests { TestItem { id: "synchronous passing test".to_string(), name: "synchronous passing test".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 5, @@ -294,6 +295,7 @@ mod tests { TestItem { id: "synchronous failing test".to_string(), name: "synchronous failing test".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 10, @@ -318,6 +320,7 @@ mod tests { TestItem { id: "asynchronous passing test".to_string(), name: "asynchronous passing test".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 15, @@ -342,6 +345,7 @@ mod tests { TestItem { id: "asynchronous failing test".to_string(), name: "asynchronous failing test".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 21, @@ -366,6 +370,7 @@ mod tests { TestItem { id: "failing test using Promises".to_string(), name: "failing test using Promises".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 27, @@ -390,6 +395,7 @@ mod tests { TestItem { id: "callback passing test".to_string(), name: "callback passing test".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 36, @@ -414,6 +420,7 @@ mod tests { TestItem { id: "callback failing test".to_string(), name: "callback failing test".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 42, @@ -438,6 +445,7 @@ mod tests { TestItem { id: "top level test".to_string(), name: "top level test".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 51, @@ -462,6 +470,7 @@ mod tests { TestItem { id: "skip option".to_string(), name: "skip option".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 63, @@ -486,6 +495,7 @@ mod tests { TestItem { id: "skip option with message".to_string(), name: "skip option with message".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 68, @@ -510,6 +520,7 @@ mod tests { TestItem { id: "skip() method".to_string(), name: "skip() method".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 72, @@ -534,6 +545,7 @@ mod tests { TestItem { id: "skip() method with message".to_string(), name: "skip() method with message".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 77, @@ -558,6 +570,7 @@ mod tests { TestItem { id: "todo option".to_string(), name: "todo option".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 84, @@ -582,6 +595,7 @@ mod tests { TestItem { id: "todo option with message".to_string(), name: "todo option with message".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 90, @@ -606,6 +620,7 @@ mod tests { TestItem { id: "todo() method".to_string(), name: "todo() method".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 94, @@ -630,6 +645,7 @@ mod tests { TestItem { id: "todo() method with message".to_string(), name: "todo() method with message".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 98, @@ -654,6 +670,7 @@ mod tests { TestItem { id: "A thing::should work".to_string(), name: "A thing::should work".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 105, @@ -678,6 +695,7 @@ mod tests { TestItem { id: "A thing::should be ok".to_string(), name: "A thing::should be ok".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 109, @@ -702,6 +720,7 @@ mod tests { TestItem { id: "A thing::a nested thing::should work".to_string(), name: "A thing::a nested thing::should work".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 114, @@ -726,6 +745,7 @@ mod tests { TestItem { id: "only: this test is run".to_string(), name: "only: this test is run".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 123, @@ -750,6 +770,7 @@ mod tests { TestItem { id: "only: this test is not run".to_string(), name: "only: this test is not run".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 142, @@ -774,6 +795,7 @@ mod tests { TestItem { id: "A suite::this test is run A ".to_string(), name: "A suite::this test is run A ".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 149, @@ -798,6 +820,7 @@ mod tests { TestItem { id: "A suite::this test is not run B".to_string(), name: "A suite::this test is not run B".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 153, @@ -822,6 +845,7 @@ mod tests { TestItem { id: "this test is run C".to_string(), name: "this test is run C".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 161, @@ -846,6 +870,7 @@ mod tests { TestItem { id: "this test is run D".to_string(), name: "this test is run D".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 165, @@ -870,6 +895,7 @@ mod tests { TestItem { id: "import from external file. this must be fail".to_string(), name: "import from external file. this must be fail".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 170, diff --git a/crates/adapter/src/runner/phpunit.rs b/crates/adapter/src/runner/phpunit.rs index dcca31f..d493899 100644 --- a/crates/adapter/src/runner/phpunit.rs +++ b/crates/adapter/src/runner/phpunit.rs @@ -240,6 +240,7 @@ mod tests { TestItem { id: "CalculatorTest::testAdd".to_string(), name: "CalculatorTest::testAdd".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 9, @@ -264,6 +265,7 @@ mod tests { TestItem { id: "CalculatorTest::testSubtract".to_string(), name: "CalculatorTest::testSubtract".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 16, @@ -288,6 +290,7 @@ mod tests { TestItem { id: "CalculatorTest::testFail1".to_string(), name: "CalculatorTest::testFail1".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 23, diff --git a/crates/adapter/src/runner/util.rs b/crates/adapter/src/runner/util.rs index ca540de..4cee602 100644 --- a/crates/adapter/src/runner/util.rs +++ b/crates/adapter/src/runner/util.rs @@ -240,6 +240,7 @@ pub fn discover_with_treesitter( let test_item = TestItem { id: test_id.clone(), name: test_id, + path: file_path.to_string(), start_position: Range { start: Position { line: test_start_position.row as u32, @@ -293,18 +294,21 @@ pub fn parse_cargo_diagnostics( // relaive path let relative_file_path = m.get(2).unwrap().as_str().to_string(); - // name of the file without extension - let file_stem = Path::new(&relative_file_path) - .file_stem() - .unwrap() - .to_str() - .unwrap(); - let executed_test_id = id_with_file.replace(&(file_stem.to_string() + "::"), ""); if let Some(file_path) = file_paths.iter().find(|path| { path.contains(workspace_root.join(&relative_file_path).to_str().unwrap()) }) { - let matched_test_item = test_items.iter().find(|item| item.id == executed_test_id); + let matched_test_item = test_items.iter().find(|item| { + let item_path = item.path.strip_prefix(workspace_root.to_str().unwrap()).unwrap_or(&item.path); + let item_path = item_path.strip_suffix(".rs").unwrap_or(item_path); + let item_path = item_path.replace('/', "::") + .replace("::src::lib", "") + .replace("::src::main", "") + .replace("::src::", ""); + let exact_id = format!("{}::{}", item_path, item.id); + tracing::info!("DEBUGPRINT[7]: util.rs:301: item_path={:#?}, exact_id={:#?}, id_with_file={:#?}", item_path, exact_id, id_with_file); + exact_id == id_with_file + }); let lnum = m.get(3).unwrap().as_str().parse::().unwrap() - 1; let col = m.get(4).unwrap().as_str().parse::().unwrap() - 1; @@ -358,7 +362,7 @@ pub fn parse_cargo_diagnostics( ..Diagnostic::default() }; result_map - .entry(file_path.to_string()) + .entry(test_item.path.to_string()) .or_default() .push(diagnostic); } diff --git a/crates/adapter/src/runner/vitest.rs b/crates/adapter/src/runner/vitest.rs index 3cab43d..48d8828 100644 --- a/crates/adapter/src/runner/vitest.rs +++ b/crates/adapter/src/runner/vitest.rs @@ -213,6 +213,7 @@ mod tests { TestItem { id: "describe text::pass".to_string(), name: "describe text::pass".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 4, @@ -237,6 +238,7 @@ mod tests { TestItem { id: "describe text::fail".to_string(), name: "describe text::fail".to_string(), + path: file_path.to_string(), start_position: Range { start: Position { line: 8, From 7b56fbcbe4db7b475b2b04da7d459ef70b3f5789 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 25 Dec 2024 23:35:07 +0900 Subject: [PATCH 132/139] feat: remove "\n" prefix in node test diagnostic message --- crates/adapter/src/runner/node_test.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/adapter/src/runner/node_test.rs b/crates/adapter/src/runner/node_test.rs index ebfbf83..7b0b639 100644 --- a/crates/adapter/src/runner/node_test.rs +++ b/crates/adapter/src/runner/node_test.rs @@ -100,7 +100,8 @@ fn get_result_from_characters( continue; } return Ok(ResultFromXml { - message: error_text.to_string(), + // remove prefix because it's like "\n" + message: error_text.strip_prefix("\n").unwrap().to_string(), path: file_path.to_string(), line: caps[2].parse::().unwrap(), col: caps[3].parse::().unwrap(), From 87d463c36e2635749317eb7db74e66da399e3108 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 25 Dec 2024 23:35:49 +0900 Subject: [PATCH 133/139] chore(adpater); v0.1.2 --- Cargo.lock | 10 +++++----- crates/adapter/Cargo.toml | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 027c433..ef73e71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -723,9 +723,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00b929d5091ea09e1a4cc4301042727e0f8445431db22944d604c3f31100375" +version = "0.1.10" dependencies = [ "anyhow", "chrono", @@ -750,6 +748,8 @@ dependencies = [ [[package]] name = "testing-language-server" version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70cedb2999008b364b1686c77a9e34531f1a31095f3177cfc11500d0ab5bd727" dependencies = [ "anyhow", "chrono", @@ -773,7 +773,7 @@ dependencies = [ [[package]] name = "testing-ls-adapter" -version = "0.1.1" +version = "0.1.2" dependencies = [ "anyhow", "clap", @@ -783,7 +783,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.1.9", + "testing-language-server 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/crates/adapter/Cargo.toml b/crates/adapter/Cargo.toml index e9680d5..1304684 100644 --- a/crates/adapter/Cargo.toml +++ b/crates/adapter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-ls-adapter" -version = "0.1.1" +version = "0.1.2" edition = "2021" description = "testing-language-server adapter" license = "MIT" @@ -8,7 +8,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -testing-language-server = "0.1.8" +testing-language-server = "0.1.10" lsp-types = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } From 969010845a6022fdb1cd7f86ce97d826919d068c Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 4 Jan 2025 19:12:28 +0900 Subject: [PATCH 134/139] docs: update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 74ae301..b254f38 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ cargo install testing-ls-adapter - [x] Realtime testing diagnostics - [x] [VSCode extension](https://github.com/kbwo/vscode-testing-ls) - [x] [coc.nvim extension](https://github.com/kbwo/coc-testing-ls) -- [x] For Neovim builtin LSP, see [demo/README.md](./demo/README.md) +- [x] For Neovim builtin LSP, see [testing-ls.nvim](https://github.com/kbwo/testing-ls.nvim) - [ ] More efficient checking of diagnostics - [ ] Useful commands in each extension From 03c298280b6edf4a4e572ec270b5204cd208a1ef Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 4 Jan 2025 19:12:40 +0900 Subject: [PATCH 135/139] chore: remove debug log --- src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index a0b2fb3..965dcb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,6 @@ fn main_loop(server: &mut TestingLS) -> Result<(), LSError> { let stdin = io::stdin(); let mut handle = stdin.lock(); handle.read_line(&mut buffer)?; - tracing::info!("DEBUGPRINT[3]: main.rs:42: buffer={:#?}", buffer); if buffer.is_empty() { tracing::warn!("buffer is empty") From b8c0aa330c55001a3624a07e27d48835ad09a873 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 4 Jan 2025 19:14:18 +0900 Subject: [PATCH 136/139] docs: update README --- README.md | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/README.md b/README.md index b254f38..cd12e1b 100644 --- a/README.md +++ b/README.md @@ -102,28 +102,7 @@ You can see the example in [See more example](./.vim/coc-settings.json) ### Neovim (nvim-lspconfig) -```lua -local lspconfig = require('lspconfig') -local configs = require('lspconfig.configs') -local util = require "lspconfig/util" - -configs.testing_ls = { - default_config = { - cmd = { "testing-language-server" }, - filetypes = {}, - root_dir = util.root_pattern(".testingls.toml", ".git" ), - }, - docs = { - description = [[ - https://github.com/kbwo/testing-language-server - - Language Server for real-time testing. - ]], - }, -} - -lspconfig.testing_ls.setup{} -``` +See [testing-ls.nvim](https://github.com/kbwo/testing-ls.nvim) ### Helix See [language.toml](./demo/.helix/language.toml). From 48af0e012ceda9440d3b5e15bb23403cc2c20ec5 Mon Sep 17 00:00:00 2001 From: kbwo Date: Sat, 4 Jan 2025 19:14:37 +0900 Subject: [PATCH 137/139] chore: v0.1.11 --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef73e71..59ffb4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -724,6 +724,8 @@ dependencies = [ [[package]] name = "testing-language-server" version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70cedb2999008b364b1686c77a9e34531f1a31095f3177cfc11500d0ab5bd727" dependencies = [ "anyhow", "chrono", @@ -747,9 +749,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70cedb2999008b364b1686c77a9e34531f1a31095f3177cfc11500d0ab5bd727" +version = "0.1.11" dependencies = [ "anyhow", "chrono", @@ -783,7 +783,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "testing-language-server 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "testing-language-server 0.1.10", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 7eb2649..36085b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.10" +version = "0.1.11" edition = "2021" description = "LSP server for testing" license = "MIT" From df261d6756ede66c6c8c3b73b08263302baf4cc8 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 29 Jan 2025 22:50:01 +0900 Subject: [PATCH 138/139] fix: avoid incremental syncing Basically, this LSP server diagnose code when saved --- src/server.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/server.rs b/src/server.rs index e5003c4..2ba8e8c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -128,9 +128,7 @@ impl TestingLS { workspace_diagnostics: true, work_done_progress_options: WorkDoneProgressOptions::default(), })), - text_document_sync: Some(TextDocumentSyncCapability::Kind( - TextDocumentSyncKind::INCREMENTAL, - )), + text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::NONE)), ..ServerCapabilities::default() } } From c53cdb6a6b5f8ee6b337c640a16ee3565fac94f2 Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 29 Jan 2025 22:53:06 +0900 Subject: [PATCH 139/139] chore: v0.1.12 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59ffb4a..30dcbf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -749,7 +749,7 @@ dependencies = [ [[package]] name = "testing-language-server" -version = "0.1.11" +version = "0.1.12" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 36085b3..97415af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testing-language-server" -version = "0.1.11" +version = "0.1.12" edition = "2021" description = "LSP server for testing" license = "MIT"