From 6c77af09c966356a0018c912418c5d8fb271079e Mon Sep 17 00:00:00 2001 From: kbwo Date: Fri, 25 Oct 2024 00:40:19 +0900 Subject: [PATCH 1/3] 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 2/3] 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 c6d839395d339099bdbfd74e8926d99a80fa632f Mon Sep 17 00:00:00 2001 From: kbwo Date: Wed, 30 Oct 2024 23:37:00 +0900 Subject: [PATCH 3/3] doc: update README --- README.md | 113 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 33 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: - -``` -"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/**/*"] - } - ] +### 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) + +### 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