mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-03 17:58:17 +00:00
test: base snapshot testing for goto definition
This commit is contained in:
parent
505164f210
commit
279bead9e1
13 changed files with 214 additions and 14 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -289,6 +289,16 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.15.3"
|
||||
|
@ -1302,6 +1312,19 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[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 = "h2"
|
||||
version = "0.3.24"
|
||||
|
@ -1768,9 +1791,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e"
|
||||
dependencies = [
|
||||
"console",
|
||||
"globset",
|
||||
"lazy_static",
|
||||
"linked-hash-map",
|
||||
"similar",
|
||||
"walkdir",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
|
|
|
@ -66,7 +66,13 @@ serde = { version = "1", features = ["derive"] }
|
|||
serde_json = "1"
|
||||
|
||||
divan = "0.1.7"
|
||||
insta = "1.34"
|
||||
insta = { vesrion = "1.34", features = ["glob"] }
|
||||
|
||||
[profile.dev.package.insta]
|
||||
opt-level = 3
|
||||
|
||||
[profile.dev.package.similar]
|
||||
opt-level = 3
|
||||
|
||||
[profile.release]
|
||||
lto = true # Enable link-time optimization
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#let f() = 1;
|
||||
#(/* position after */ f());
|
|
@ -0,0 +1,2 @@
|
|||
#((((let x = 1))));
|
||||
#(/* position after */ x);
|
|
@ -0,0 +1,2 @@
|
|||
#(let (x) = 2);
|
||||
#(/* position after */ x);
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/goto_definition.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/goto_definition/base.typ
|
||||
---
|
||||
[
|
||||
{
|
||||
"originSelectionRange": "1:23:1:24",
|
||||
"targetRange": "0:6:0:8",
|
||||
"targetSelectionRange": "0:6:0:8"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/goto_definition.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/goto_definition/paren.typ
|
||||
---
|
||||
[
|
||||
{
|
||||
"originSelectionRange": "1:23:1:24",
|
||||
"targetRange": "0:5:0:14",
|
||||
"targetSelectionRange": "0:5:0:14"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/goto_definition.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/goto_definition/paren_lhs.typ
|
||||
---
|
||||
[
|
||||
{
|
||||
"originSelectionRange": "1:23:1:24",
|
||||
"targetRange": "0:2:0:13",
|
||||
"targetSelectionRange": "0:2:0:13"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/goto_definition.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/goto_definition/variable.typ
|
||||
---
|
||||
[
|
||||
{
|
||||
"originSelectionRange": "1:23:1:24",
|
||||
"targetRange": "0:1:0:10",
|
||||
"targetSelectionRange": "0:1:0:10"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,2 @@
|
|||
#let x = 1;
|
||||
#(/* position after */ x);
|
2
crates/tinymist-query/src/fixtures/playground/base.typ
Normal file
2
crates/tinymist-query/src/fixtures/playground/base.typ
Normal file
|
@ -0,0 +1,2 @@
|
|||
#let x = 1;
|
||||
#(/* position after */ x);
|
|
@ -58,3 +58,25 @@ impl GotoDefinitionRequest {
|
|||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::tests::*;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
// goto_definition
|
||||
snapshot_testing("goto_definition", &|world, path| {
|
||||
let source = get_suitable_source_in_workspace(world, &path).unwrap();
|
||||
|
||||
let request = GotoDefinitionRequest {
|
||||
path: path.clone(),
|
||||
position: find_test_position(&source),
|
||||
};
|
||||
|
||||
let result = request.request(world, PositionEncoding::Utf16);
|
||||
assert_snapshot!(JsonRepr::new_redacted(result, &REDACT_LOC));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,13 +145,30 @@ mod tests {
|
|||
use once_cell::sync::Lazy;
|
||||
use serde::Serialize;
|
||||
use serde_json::{ser::PrettyFormatter, Serializer, Value};
|
||||
use typst_ts_compiler::ShadowApiExt;
|
||||
use typst_ts_core::{config::CompileOpts, Bytes};
|
||||
use typst::syntax::{LinkedNode, Source, VirtualPath};
|
||||
use typst_ts_compiler::{service::WorkspaceProvider, ShadowApi};
|
||||
use typst_ts_core::{config::CompileOpts, Bytes, TypstFileId};
|
||||
|
||||
pub use insta::assert_snapshot;
|
||||
pub use typst_ts_compiler::TypstSystemWorld;
|
||||
|
||||
pub fn run_with_source<T>(
|
||||
use crate::{typst_to_lsp, LspPosition, PositionEncoding};
|
||||
|
||||
pub fn snapshot_testing(name: &str, f: &impl Fn(&mut TypstSystemWorld, PathBuf)) {
|
||||
let mut settings = insta::Settings::new();
|
||||
settings.set_prepend_module_to_snapshot(false);
|
||||
settings.set_snapshot_path(format!("fixtures/{name}"));
|
||||
settings.bind(|| {
|
||||
let glob_path = format!("fixtures/{name}/*.typ");
|
||||
insta::glob!(&glob_path, |path| {
|
||||
let contents = std::fs::read_to_string(path).unwrap();
|
||||
|
||||
run_with_sources(&contents, f);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn run_with_sources<T>(
|
||||
source: &str,
|
||||
f: impl FnOnce(&mut TypstSystemWorld, PathBuf) -> T,
|
||||
) -> T {
|
||||
|
@ -165,18 +182,70 @@ mod tests {
|
|||
..Default::default()
|
||||
})
|
||||
.unwrap();
|
||||
let pw = &root.join(Path::new("/main.typ"));
|
||||
world
|
||||
.with_shadow_file(pw, Bytes::from(source.as_bytes()), move |e| {
|
||||
Ok(f(e, pw.to_owned()))
|
||||
})
|
||||
.unwrap()
|
||||
let sources = source.split("-----");
|
||||
|
||||
let mut last_pw = None;
|
||||
for (i, source) in sources.enumerate() {
|
||||
// find prelude
|
||||
let mut source = source.trim();
|
||||
let path = if source.starts_with("//") {
|
||||
let first_line = source.lines().next().unwrap();
|
||||
source = source.strip_prefix(first_line).unwrap().trim();
|
||||
|
||||
let content = first_line.strip_prefix("//").unwrap().trim();
|
||||
content.strip_prefix("path:").unwrap().trim().to_owned()
|
||||
} else {
|
||||
format!("/source{i}.typ")
|
||||
};
|
||||
|
||||
let pw = root.join(Path::new(&path));
|
||||
world
|
||||
.map_shadow(&pw, Bytes::from(source.as_bytes()))
|
||||
.unwrap();
|
||||
last_pw = Some(pw);
|
||||
}
|
||||
|
||||
let pw = last_pw.unwrap();
|
||||
world.set_main_id(TypstFileId::new(
|
||||
None,
|
||||
VirtualPath::new(pw.strip_prefix(root).unwrap()),
|
||||
));
|
||||
f(&mut world, pw)
|
||||
}
|
||||
|
||||
pub fn find_test_position(s: &Source) -> LspPosition {
|
||||
let re = s.text().find("/* position */").map(|e| (e, true));
|
||||
let re = re.or_else(|| s.text().find("/* position after */").zip(Some(false)));
|
||||
let (re, prev) = re.unwrap();
|
||||
|
||||
let n = LinkedNode::new(s.root());
|
||||
let mut n = n.leaf_at(re + 1).unwrap();
|
||||
|
||||
while n.kind().is_trivia() {
|
||||
let m = if prev {
|
||||
n.prev_sibling()
|
||||
} else {
|
||||
n.next_sibling()
|
||||
};
|
||||
n = m.or_else(|| n.parent().cloned()).unwrap();
|
||||
}
|
||||
|
||||
typst_to_lsp::offset_to_position(n.offset() + 1, PositionEncoding::Utf16, s)
|
||||
}
|
||||
|
||||
// pub static REDACT_URI: Lazy<RedactFields> = Lazy::new(||
|
||||
// RedactFields::from_iter(["uri"]));
|
||||
pub static REDACT_LOC: Lazy<RedactFields> =
|
||||
Lazy::new(|| RedactFields::from_iter(["location", "range", "selectionRange"]));
|
||||
pub static REDACT_LOC: Lazy<RedactFields> = Lazy::new(|| {
|
||||
RedactFields::from_iter([
|
||||
"location",
|
||||
"range",
|
||||
"selectionRange",
|
||||
"targetRange",
|
||||
"targetSelectionRange",
|
||||
"originSelectionRange",
|
||||
"targetUri",
|
||||
])
|
||||
});
|
||||
|
||||
pub struct JsonRepr(Value);
|
||||
|
||||
|
@ -219,6 +288,10 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn pos(v: &Value) -> String {
|
||||
format!("{}:{}", v["line"], v["character"])
|
||||
}
|
||||
|
||||
impl Redact for RedactFields {
|
||||
fn redact(&self, v: Value) -> Value {
|
||||
match v {
|
||||
|
@ -226,8 +299,24 @@ mod tests {
|
|||
for (_, v) in m.iter_mut() {
|
||||
*v = self.redact(v.clone());
|
||||
}
|
||||
for k in self.0.iter() {
|
||||
m.remove(*k);
|
||||
for k in self.0.iter().copied() {
|
||||
let Some(t) = m.remove(k) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
match k {
|
||||
"range"
|
||||
| "selectionRange"
|
||||
| "originSelectionRange"
|
||||
| "targetRange"
|
||||
| "targetSelectionRange" => {
|
||||
m.insert(
|
||||
k.to_owned(),
|
||||
format!("{}:{}", pos(&t["start"]), pos(&t["end"])).into(),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Value::Object(m)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue