Compare commits

...

24 commits
v0.1.8 ... main

Author SHA1 Message Date
kbwo
c53cdb6a6b chore: v0.1.12 2025-01-29 22:53:29 +09:00
kbwo
df261d6756 fix: avoid incremental syncing
Basically, this LSP server diagnose code when saved
2025-01-29 22:52:50 +09:00
kbwo
48af0e012c chore: v0.1.11 2025-01-04 19:14:37 +09:00
kbwo
b8c0aa330c docs: update README 2025-01-04 19:14:18 +09:00
kbwo
03c298280b chore: remove debug log 2025-01-04 19:12:40 +09:00
kbwo
969010845a docs: update README 2025-01-04 19:12:28 +09:00
kbwo
87d463c36e chore(adpater); v0.1.2 2024-12-25 23:35:49 +09:00
kbwo
7b56fbcbe4 feat: remove "\n" prefix in node test diagnostic message 2024-12-25 23:35:07 +09:00
kbwo
855d2c0094 feat(adapter): add path field for server v0.1.10 2024-12-25 23:34:31 +09:00
kbwo
a766099b76 chore: v0.1.10 2024-12-25 23:32:06 +09:00
kbwo
4df71f69c0 feat: add path field to TestItem for demand from adapter 2024-12-25 23:31:26 +09:00
kbwo
5b8862fe5d chore: v0.1.9 2024-12-24 18:24:52 +09:00
kbwo
833bfbc1b7 fix: prevent diagnostics to be cleared when :edit in vim 2024-12-24 18:24:37 +09:00
kbwo
42354d8ec5 refactor(server): fix for clippy 2024-12-24 17:27:42 +09:00
kbwo
5a672ddf71 chore(adapter): 0.1.1 2024-12-24 17:12:17 +09:00
kbwo
caa4463119 Merge branch 'fix/adapter-types' 2024-12-24 17:11:52 +09:00
kbwo
942f0b4ed1 fix(adapter): return valid json type to server 2024-12-24 17:11:06 +09:00
Kodai Kabasawa
91db91a229
Merge pull request #53 from kbwo/feat/update-adapter-spec
adapter: Update specification
2024-12-07 23:28:10 +09:00
kbwo
6c75bbbd47 chore(adapter): v0.1.0 2024-12-07 23:25:23 +09:00
kbwo
1df3076259 refactor: delete unused variable 2024-12-07 23:24:54 +09:00
kbwo
787e92fe87 feat(adapter): use new interface of detect-workspace 2024-12-07 23:24:28 +09:00
kbwo
df0631a6d6 feat(adapter): use new interface of discover 2024-12-07 23:24:23 +09:00
kbwo
2fa914973f feat(adapter): use new interface of run-file-test 2024-12-07 23:24:17 +09:00
kbwo
1fae0f701a chore(adapter): update adapter dependency 2024-12-07 23:24:03 +09:00
18 changed files with 226 additions and 166 deletions

12
Cargo.lock generated
View file

@ -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"
@ -723,9 +723,9 @@ dependencies = [
[[package]]
name = "testing-language-server"
version = "0.1.7"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fae6ce9cb290e80814d1796e4207a0a0dc21c216807136d48b68c0f27be29b9"
checksum = "70cedb2999008b364b1686c77a9e34531f1a31095f3177cfc11500d0ab5bd727"
dependencies = [
"anyhow",
"chrono",
@ -749,7 +749,7 @@ dependencies = [
[[package]]
name = "testing-language-server"
version = "0.1.8"
version = "0.1.12"
dependencies = [
"anyhow",
"chrono",
@ -773,7 +773,7 @@ dependencies = [
[[package]]
name = "testing-ls-adapter"
version = "0.0.11"
version = "0.1.2"
dependencies = [
"anyhow",
"clap",
@ -783,7 +783,7 @@ dependencies = [
"serde",
"serde_json",
"tempfile",
"testing-language-server 0.1.7",
"testing-language-server 0.1.10",
"tracing",
"tracing-appender",
"tracing-subscriber",

View file

@ -1,6 +1,6 @@
[package]
name = "testing-language-server"
version = "0.1.8"
version = "0.1.12"
edition = "2021"
description = "LSP server for testing"
license = "MIT"

View file

@ -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
@ -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).

View file

@ -1,6 +1,6 @@
[package]
name = "testing-ls-adapter"
version = "0.0.11"
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.7"
testing-language-server = "0.1.10"
lsp-types = { workspace = true }
serde_json = { workspace = true }
serde = { workspace = true }

View file

@ -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<WorkerGuard, anyhow::Error> {

View file

@ -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;
@ -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(FoundFileTests {
tests,
path: file_path,
});
@ -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;
@ -136,6 +136,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
let test_items: Vec<TestItem> = 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,
@ -171,24 +172,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!()
}
)
}
@ -211,8 +215,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()));
}
}

View file

@ -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;
@ -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(FoundFileTests {
tests,
path: file_path,
});
@ -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;
@ -131,6 +131,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
let test_items: Vec<TestItem> = 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,
@ -166,24 +167,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![]
}
)
}
@ -206,8 +210,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()));
}
}

View file

@ -13,9 +13,9 @@ 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::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<String>) -> DetectWorkspaceResult {
@ -161,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(FoundFileTests {
tests: discover(&file_path)?,
path: file_path,
})
@ -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]
@ -242,8 +245,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());
});
}
@ -260,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,
@ -284,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,
@ -308,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,

View file

@ -13,9 +13,9 @@ 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::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<Vec<TestItem>, LSError> {
@ -232,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(FoundFileTests {
tests,
path: file_path,
});
@ -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);

View file

@ -8,9 +8,9 @@ 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::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<String>) -> DetectWorkspaceResult {
@ -159,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(FoundFileTests {
tests: discover(&file_path)?,
path: file_path,
})
@ -229,7 +232,7 @@ mod tests {
],
)
.unwrap();
assert_eq!(diagnostics.len(), 2);
assert_eq!(diagnostics.data.len(), 2);
}
#[test]
@ -242,8 +245,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());
});
}
@ -258,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,

View file

@ -4,8 +4,8 @@ use regex::Regex;
use testing_language_server::{
error::LSError,
spec::{
DetectWorkspaceResult, DiscoverResult, DiscoverResultItem, RunFileTestResult,
RunFileTestResultItem, TestItem,
DetectWorkspaceResult, DiscoverResult, FileDiagnostics, FoundFileTests, RunFileTestResult,
TestItem,
},
};
use xml::{reader::XmlEvent, ParserConfig};
@ -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::<u32>().unwrap(),
col: caps[3].parse::<u32>().unwrap(),
@ -162,9 +163,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(FoundFileTests {
tests: discover(&file_path)?,
path: file_path,
})
@ -194,14 +195,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<FileDiagnostics> = 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(())
}
@ -266,6 +271,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,
@ -290,6 +296,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,
@ -314,6 +321,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,
@ -338,6 +346,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,
@ -362,6 +371,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,
@ -386,6 +396,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,
@ -410,6 +421,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,
@ -434,6 +446,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,
@ -458,6 +471,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,
@ -482,6 +496,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,
@ -506,6 +521,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,
@ -530,6 +546,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,
@ -554,6 +571,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,
@ -578,6 +596,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,
@ -602,6 +621,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,
@ -626,6 +646,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,
@ -650,6 +671,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,
@ -674,6 +696,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,
@ -698,6 +721,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,
@ -722,6 +746,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,
@ -746,6 +771,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,
@ -770,6 +796,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,
@ -794,6 +821,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,
@ -818,6 +846,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,
@ -842,6 +871,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,
@ -866,6 +896,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,

View file

@ -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, FileDiagnostics, FoundFileTests, RunFileTestResult,
TestItem,
};
use xml::reader::{ParserConfig, XmlEvent};
@ -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(FoundFileTests {
tests: discover(&file_path)?,
path: file_path,
})
@ -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<FileDiagnostics> = 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(())
}
@ -236,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,
@ -260,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,
@ -284,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,

View file

@ -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::{DetectWorkspaceResult, 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<RunFileTestResultItem> for ResultFromXml {
fn into(self) -> RunFileTestResultItem {
RunFileTestResultItem {
#[allow(clippy::from_over_into)]
impl Into<FileDiagnostics> for ResultFromXml {
fn into(self) -> FileDiagnostics {
FileDiagnostics {
path: self.path,
diagnostics: vec![Diagnostic {
message: self.message,
@ -73,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<String, Vec<String>> {
) -> DetectWorkspaceResult {
let mut result_map: HashMap<String, Vec<String>> = HashMap::new();
let mut file_paths = target_file_paths.to_vec();
file_paths.sort_by_key(|b| b.len());
@ -105,7 +106,7 @@ pub fn detect_workspaces_from_file_list(
}
}
}
result_map
DetectWorkspaceResult { data: result_map }
}
pub fn send_stdout<T>(value: &T) -> Result<(), LSError>
@ -239,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,
@ -292,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::<u32>().unwrap() - 1;
let col = m.get(4).unwrap().as_str().parse::<u32>().unwrap() - 1;
@ -357,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);
}
@ -371,10 +376,15 @@ pub fn parse_cargo_diagnostics(
}
}
result_map
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

View file

@ -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, FileDiagnostics, FoundFileTests, RunFileTestResult, TestItem},
};
use crate::model::Runner;
@ -124,21 +122,24 @@ 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 {
#[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(FoundFileTests {
tests,
path: file_path,
});
@ -212,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,
@ -236,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,

View file

@ -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<WorkerGuard, anyhow::Error> {

View file

@ -74,11 +74,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 +88,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 +124,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 +135,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,

View file

@ -128,6 +128,7 @@ impl TestingLS {
workspace_diagnostics: true,
work_done_progress_options: WorkDoneProgressOptions::default(),
})),
text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::NONE)),
..ServerCapabilities::default()
}
}

View file

@ -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,
}