diff options
| author | Laurenz <laurmaedje@gmail.com> | 2024-12-18 20:26:39 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-18 19:26:39 +0000 |
| commit | db06dbf9763d6c610d1f7a267597ecdad309048a (patch) | |
| tree | 8097482d98e6a42f42ab16447848e58076bcb836 /crates/typst-ide/src/tests.rs | |
| parent | 45c866fbb947715cfee1937c85d6d6d6f393d7a8 (diff) | |
Further improve IDE tests (#5602)
Diffstat (limited to 'crates/typst-ide/src/tests.rs')
| -rw-r--r-- | crates/typst-ide/src/tests.rs | 95 |
1 files changed, 71 insertions, 24 deletions
diff --git a/crates/typst-ide/src/tests.rs b/crates/typst-ide/src/tests.rs index 5a73fa37..f41808da 100644 --- a/crates/typst-ide/src/tests.rs +++ b/crates/typst-ide/src/tests.rs @@ -1,4 +1,6 @@ +use std::borrow::Borrow; use std::collections::HashMap; +use std::sync::Arc; use ecow::EcoString; use typst::diag::{FileError, FileResult}; @@ -13,10 +15,10 @@ use typst::{Library, World}; use crate::IdeWorld; /// A world for IDE testing. +#[derive(Clone)] pub struct TestWorld { pub main: Source, - assets: HashMap<FileId, Bytes>, - sources: HashMap<FileId, Source>, + files: Arc<TestFiles>, base: &'static TestBase, } @@ -29,8 +31,7 @@ impl TestWorld { let main = Source::new(Self::main_id(), text.into()); Self { main, - assets: HashMap::new(), - sources: HashMap::new(), + files: Arc::new(TestFiles::default()), base: singleton!(TestBase, TestBase::default()), } } @@ -39,7 +40,7 @@ impl TestWorld { pub fn with_source(mut self, path: &str, text: &str) -> Self { let id = FileId::new(None, VirtualPath::new(path)); let source = Source::new(id, text.into()); - self.sources.insert(id, source); + Arc::make_mut(&mut self.files).sources.insert(id, source); self } @@ -55,7 +56,7 @@ impl TestWorld { let id = FileId::new(None, VirtualPath::new(path)); let data = typst_dev_assets::get_by_name(filename).unwrap(); let bytes = Bytes::from_static(data); - self.assets.insert(id, bytes); + Arc::make_mut(&mut self.files).assets.insert(id, bytes); self } @@ -81,7 +82,7 @@ impl World for TestWorld { fn source(&self, id: FileId) -> FileResult<Source> { if id == self.main.id() { Ok(self.main.clone()) - } else if let Some(source) = self.sources.get(&id) { + } else if let Some(source) = self.files.sources.get(&id) { Ok(source.clone()) } else { Err(FileError::NotFound(id.vpath().as_rootless_path().into())) @@ -89,7 +90,7 @@ impl World for TestWorld { } fn file(&self, id: FileId) -> FileResult<Bytes> { - match self.assets.get(&id) { + match self.files.assets.get(&id) { Some(bytes) => Ok(bytes.clone()), None => Err(FileError::NotFound(id.vpath().as_rootless_path().into())), } @@ -111,8 +112,8 @@ impl IdeWorld for TestWorld { fn files(&self) -> Vec<FileId> { std::iter::once(self.main.id()) - .chain(self.sources.keys().copied()) - .chain(self.assets.keys().copied()) + .chain(self.files.sources.keys().copied()) + .chain(self.files.assets.keys().copied()) .collect() } @@ -133,20 +134,11 @@ impl IdeWorld for TestWorld { } } -/// Extra methods for [`Source`]. -pub trait SourceExt { - /// Negative cursors index from the back. - fn cursor(&self, cursor: isize) -> usize; -} - -impl SourceExt for Source { - fn cursor(&self, cursor: isize) -> usize { - if cursor < 0 { - self.len_bytes().checked_add_signed(cursor).unwrap() - } else { - cursor as usize - } - } +/// Test-specific files. +#[derive(Default, Clone)] +struct TestFiles { + assets: HashMap<FileId, Bytes>, + sources: HashMap<FileId, Source>, } /// Shared foundation of all test worlds. @@ -186,3 +178,58 @@ fn library() -> Library { lib.styles.set(TextElem::set_size(TextSize(Abs::pt(10.0).into()))); lib } + +/// The input to a test: Either just a string or a full `TestWorld`. +pub trait WorldLike { + type World: Borrow<TestWorld>; + + fn acquire(self) -> Self::World; +} + +impl<'a> WorldLike for &'a TestWorld { + type World = &'a TestWorld; + + fn acquire(self) -> Self::World { + self + } +} + +impl WorldLike for &str { + type World = TestWorld; + + fn acquire(self) -> Self::World { + TestWorld::new(self) + } +} + +/// Specifies a position in a file for a test. +pub trait FilePos { + fn resolve(self, world: &TestWorld) -> (Source, usize); +} + +impl FilePos for isize { + #[track_caller] + fn resolve(self, world: &TestWorld) -> (Source, usize) { + (world.main.clone(), cursor(&world.main, self)) + } +} + +impl FilePos for (&str, isize) { + #[track_caller] + fn resolve(self, world: &TestWorld) -> (Source, usize) { + let id = FileId::new(None, VirtualPath::new(self.0)); + let source = world.source(id).unwrap(); + let cursor = cursor(&source, self.1); + (source, cursor) + } +} + +/// Resolve a signed index (negative from the back) to a unsigned index. +#[track_caller] +fn cursor(source: &Source, cursor: isize) -> usize { + if cursor < 0 { + source.len_bytes().checked_add_signed(cursor + 1).unwrap() + } else { + cursor as usize + } +} |
