tinymist_project/
mock.rs

1//! Mock project compiler support for Tinymist tests.
2//!
3//! This module intentionally lives in `tinymist-project` so project-runtime
4//! tests can drive compiler interrupts without depending on aggregate
5//! test-support crates. Enable the `mock` feature from downstream
6//! test-support crates when this module is needed as a dependency.
7
8use tinymist_world::{
9    mock::{MockCompilerFeat, MockWorldBuilder},
10    vfs::{mock::MockChange, notify::NotifyMessage},
11};
12use tokio::sync::mpsc;
13
14use crate::{CompileServerOpts, Interrupt, ProjectCompiler};
15
16/// A project compiler backed by mock VFS and world components.
17pub type MockProjectCompiler<Ext = ()> = ProjectCompiler<MockCompilerFeat, Ext>;
18
19/// Extension helpers for building project compilers from mock world builders.
20pub trait MockProjectBuilderExt {
21    /// Builds a syntax-only project compiler and its notify receiver.
22    fn project_compiler<Ext>(
23        &self,
24    ) -> typst::diag::FileResult<(
25        MockProjectCompiler<Ext>,
26        mpsc::UnboundedReceiver<NotifyMessage>,
27    )>
28    where
29        Ext: Default + 'static;
30
31    /// Builds a project compiler with custom options and its notify receiver.
32    fn project_compiler_with_opts<Ext>(
33        &self,
34        opts: CompileServerOpts<MockCompilerFeat, Ext>,
35    ) -> typst::diag::FileResult<(
36        MockProjectCompiler<Ext>,
37        mpsc::UnboundedReceiver<NotifyMessage>,
38    )>
39    where
40        Ext: Default + 'static;
41}
42
43impl MockProjectBuilderExt for MockWorldBuilder {
44    fn project_compiler<Ext>(
45        &self,
46    ) -> typst::diag::FileResult<(
47        MockProjectCompiler<Ext>,
48        mpsc::UnboundedReceiver<NotifyMessage>,
49    )>
50    where
51        Ext: Default + 'static,
52    {
53        self.project_compiler_with_opts(CompileServerOpts {
54            syntax_only: true,
55            ..Default::default()
56        })
57    }
58
59    fn project_compiler_with_opts<Ext>(
60        &self,
61        opts: CompileServerOpts<MockCompilerFeat, Ext>,
62    ) -> typst::diag::FileResult<(
63        MockProjectCompiler<Ext>,
64        mpsc::UnboundedReceiver<NotifyMessage>,
65    )>
66    where
67        Ext: Default + 'static,
68    {
69        let (tx, rx) = mpsc::unbounded_channel();
70        Ok((ProjectCompiler::new(self.build_universe()?, tx, opts), rx))
71    }
72}
73
74/// Applies VFS mock changes to project compilers.
75pub trait MockProjectChangeExt {
76    /// Applies this change to a project compiler as a filesystem event.
77    fn apply_as_fs_to_project<F, Ext>(&self, compiler: &mut ProjectCompiler<F, Ext>, is_sync: bool)
78    where
79        F: tinymist_world::CompilerFeat + Send + Sync + 'static,
80        Ext: Default + 'static;
81
82    /// Applies this change to a project compiler as a memory event.
83    fn apply_as_memory_to_project<F, Ext>(&self, compiler: &mut ProjectCompiler<F, Ext>)
84    where
85        F: tinymist_world::CompilerFeat + Send + Sync + 'static,
86        Ext: Default + 'static;
87}
88
89impl MockProjectChangeExt for MockChange {
90    fn apply_as_fs_to_project<F, Ext>(&self, compiler: &mut ProjectCompiler<F, Ext>, is_sync: bool)
91    where
92        F: tinymist_world::CompilerFeat + Send + Sync + 'static,
93        Ext: Default + 'static,
94    {
95        compiler.process(Interrupt::Fs(self.filesystem_event(is_sync)));
96    }
97
98    fn apply_as_memory_to_project<F, Ext>(&self, compiler: &mut ProjectCompiler<F, Ext>)
99    where
100        F: tinymist_world::CompilerFeat + Send + Sync + 'static,
101        Ext: Default + 'static,
102    {
103        compiler.process(Interrupt::Memory(self.memory_event()));
104    }
105}