mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-07 21:15:03 +00:00
feat: pass tests if warnings happens (#1535)
This commit is contained in:
parent
4bb16b5b93
commit
c8c891fbc3
6 changed files with 61 additions and 51 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,3 +12,4 @@ editors/lapce/out/
|
||||||
|
|
||||||
*.pdf
|
*.pdf
|
||||||
.vscode/*.code-workspace
|
.vscode/*.code-workspace
|
||||||
|
refs/
|
|
@ -66,6 +66,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: CompilerFeat, I: Instrumenter> SourceWorld for InstrumentWorld<'_, F, I> {
|
impl<F: CompilerFeat, I: Instrumenter> SourceWorld for InstrumentWorld<'_, F, I> {
|
||||||
|
fn as_world(&self) -> &dyn typst::World {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn path_for_id(&self, id: FileId) -> FileResult<PathResolution> {
|
fn path_for_id(&self, id: FileId) -> FileResult<PathResolution> {
|
||||||
self.base.path_for_id(id)
|
self.base.path_for_id(id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,5 @@ pub use tinymist_world::entry::*;
|
||||||
pub use tinymist_world::{font, package, system, vfs};
|
pub use tinymist_world::{font, package, system, vfs};
|
||||||
pub use tinymist_world::{
|
pub use tinymist_world::{
|
||||||
with_main, CompilerUniverse, CompilerWorld, DiagnosticFormat, EntryOpts, EntryState,
|
with_main, CompilerUniverse, CompilerWorld, DiagnosticFormat, EntryOpts, EntryState,
|
||||||
RevisingUniverse, TaskInputs,
|
RevisingUniverse, SourceWorld, TaskInputs,
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,9 +11,9 @@ use tinymist_std::Result;
|
||||||
use tinymist_vfs::FileId;
|
use tinymist_vfs::FileId;
|
||||||
use typst::diag::{eco_format, Severity, SourceDiagnostic};
|
use typst::diag::{eco_format, Severity, SourceDiagnostic};
|
||||||
use typst::syntax::Span;
|
use typst::syntax::Span;
|
||||||
use typst::{World, WorldExt};
|
use typst::WorldExt;
|
||||||
|
|
||||||
use crate::{DiagnosticFormat, SourceWorld};
|
use crate::{CodeSpanReportWorld, DiagnosticFormat, SourceWorld};
|
||||||
|
|
||||||
/// Get stderr with color support if desirable.
|
/// Get stderr with color support if desirable.
|
||||||
fn color_stream() -> StandardStream {
|
fn color_stream() -> StandardStream {
|
||||||
|
@ -25,12 +25,12 @@ fn color_stream() -> StandardStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print diagnostic messages to the terminal.
|
/// Print diagnostic messages to the terminal.
|
||||||
pub fn print_diagnostics<'d, 'files, W: SourceWorld>(
|
pub fn print_diagnostics<'d, 'files>(
|
||||||
world: &'files W,
|
world: &'files dyn SourceWorld,
|
||||||
errors: impl Iterator<Item = &'d SourceDiagnostic>,
|
errors: impl Iterator<Item = &'d SourceDiagnostic>,
|
||||||
diagnostic_format: DiagnosticFormat,
|
diagnostic_format: DiagnosticFormat,
|
||||||
) -> Result<(), codespan_reporting::files::Error> {
|
) -> Result<(), codespan_reporting::files::Error> {
|
||||||
let world = world.for_codespan_reporting();
|
let world = CodeSpanReportWorld::new(world);
|
||||||
|
|
||||||
let mut w = match diagnostic_format {
|
let mut w = match diagnostic_format {
|
||||||
DiagnosticFormat::Human => color_stream(),
|
DiagnosticFormat::Human => color_stream(),
|
||||||
|
@ -77,6 +77,6 @@ pub fn print_diagnostics<'d, 'files, W: SourceWorld>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a label for a span.
|
/// Create a label for a span.
|
||||||
fn label<W: World>(world: &W, span: Span) -> Option<Label<FileId>> {
|
fn label(world: &dyn SourceWorld, span: Span) -> Option<Label<FileId>> {
|
||||||
Some(Label::primary(span.id()?, world.range(span)?))
|
Some(Label::primary(span.id()?, world.range(span)?))
|
||||||
}
|
}
|
||||||
|
|
|
@ -772,43 +772,37 @@ impl typst::World for WorldWithMain<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SourceWorld: World {
|
pub trait SourceWorld: World {
|
||||||
|
fn as_world(&self) -> &dyn World;
|
||||||
|
|
||||||
fn path_for_id(&self, id: FileId) -> Result<PathResolution, FileError>;
|
fn path_for_id(&self, id: FileId) -> Result<PathResolution, FileError>;
|
||||||
fn lookup(&self, id: FileId) -> Source {
|
fn lookup(&self, id: FileId) -> Source {
|
||||||
self.source(id)
|
self.source(id)
|
||||||
.expect("file id does not point to any source file")
|
.expect("file id does not point to any source file")
|
||||||
}
|
}
|
||||||
fn map_source_or_default<T>(
|
|
||||||
&self,
|
|
||||||
id: FileId,
|
|
||||||
default_v: T,
|
|
||||||
f: impl FnOnce(Source) -> CodespanResult<T>,
|
|
||||||
) -> CodespanResult<T> {
|
|
||||||
match self.source(id).ok() {
|
|
||||||
Some(source) => f(source),
|
|
||||||
None => Ok(default_v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn for_codespan_reporting(&self) -> CodeSpanReportWorld<Self>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
CodeSpanReportWorld { world: self }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: CompilerFeat> SourceWorld for CompilerWorld<F> {
|
impl<F: CompilerFeat> SourceWorld for CompilerWorld<F> {
|
||||||
|
fn as_world(&self) -> &dyn World {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolve the real path for a file id.
|
/// Resolve the real path for a file id.
|
||||||
fn path_for_id(&self, id: FileId) -> Result<PathResolution, FileError> {
|
fn path_for_id(&self, id: FileId) -> Result<PathResolution, FileError> {
|
||||||
self.path_for_id(id)
|
self.path_for_id(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CodeSpanReportWorld<'a, T> {
|
pub struct CodeSpanReportWorld<'a> {
|
||||||
pub world: &'a T,
|
pub world: &'a dyn SourceWorld,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: SourceWorld> codespan_reporting::files::Files<'a> for CodeSpanReportWorld<'a, T> {
|
impl<'a> CodeSpanReportWorld<'a> {
|
||||||
|
pub fn new(world: &'a dyn SourceWorld) -> Self {
|
||||||
|
Self { world }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> codespan_reporting::files::Files<'a> for CodeSpanReportWorld<'a> {
|
||||||
/// A unique identifier for files in the file provider. This will be used
|
/// A unique identifier for files in the file provider. This will be used
|
||||||
/// for rendering `diagnostic::Label`s in the corresponding source files.
|
/// for rendering `diagnostic::Label`s in the corresponding source files.
|
||||||
type FileId = FileId;
|
type FileId = FileId;
|
||||||
|
@ -858,14 +852,17 @@ impl<'a, T: SourceWorld> codespan_reporting::files::Files<'a> for CodeSpanReport
|
||||||
|
|
||||||
/// See [`codespan_reporting::files::Files::line_range`].
|
/// See [`codespan_reporting::files::Files::line_range`].
|
||||||
fn line_range(&'a self, id: FileId, given: usize) -> CodespanResult<std::ops::Range<usize>> {
|
fn line_range(&'a self, id: FileId, given: usize) -> CodespanResult<std::ops::Range<usize>> {
|
||||||
self.world.map_source_or_default(id, 0..0, |source| {
|
match self.world.source(id).ok() {
|
||||||
source
|
Some(source) => {
|
||||||
.line_to_range(given)
|
source
|
||||||
.ok_or_else(|| CodespanError::LineTooLarge {
|
.line_to_range(given)
|
||||||
given,
|
.ok_or_else(|| CodespanError::LineTooLarge {
|
||||||
max: source.len_lines(),
|
given,
|
||||||
})
|
max: source.len_lines(),
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
None => Ok(0..0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,27 +880,27 @@ impl<'a, F: CompilerFeat> codespan_reporting::files::Files<'a> for CompilerWorld
|
||||||
|
|
||||||
/// The user-facing name of a file.
|
/// The user-facing name of a file.
|
||||||
fn name(&'a self, id: FileId) -> CodespanResult<Self::Name> {
|
fn name(&'a self, id: FileId) -> CodespanResult<Self::Name> {
|
||||||
self.for_codespan_reporting().name(id)
|
CodeSpanReportWorld::new(self).name(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The source code of a file.
|
/// The source code of a file.
|
||||||
fn source(&'a self, id: FileId) -> CodespanResult<Self::Source> {
|
fn source(&'a self, id: FileId) -> CodespanResult<Self::Source> {
|
||||||
self.for_codespan_reporting().source(id)
|
CodeSpanReportWorld::new(self).source(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`codespan_reporting::files::Files::line_index`].
|
/// See [`codespan_reporting::files::Files::line_index`].
|
||||||
fn line_index(&'a self, id: FileId, given: usize) -> CodespanResult<usize> {
|
fn line_index(&'a self, id: FileId, given: usize) -> CodespanResult<usize> {
|
||||||
self.for_codespan_reporting().line_index(id, given)
|
CodeSpanReportWorld::new(self).line_index(id, given)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`codespan_reporting::files::Files::column_number`].
|
/// See [`codespan_reporting::files::Files::column_number`].
|
||||||
fn column_number(&'a self, id: FileId, _: usize, given: usize) -> CodespanResult<usize> {
|
fn column_number(&'a self, id: FileId, _: usize, given: usize) -> CodespanResult<usize> {
|
||||||
self.for_codespan_reporting().column_number(id, 0, given)
|
CodeSpanReportWorld::new(self).column_number(id, 0, given)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`codespan_reporting::files::Files::line_range`].
|
/// See [`codespan_reporting::files::Files::line_range`].
|
||||||
fn line_range(&'a self, id: FileId, given: usize) -> CodespanResult<std::ops::Range<usize>> {
|
fn line_range(&'a self, id: FileId, given: usize) -> CodespanResult<std::ops::Range<usize>> {
|
||||||
self.for_codespan_reporting().line_range(id, given)
|
CodeSpanReportWorld::new(self).line_range(id, given)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,14 @@ use itertools::Either;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
use reflexo::ImmutPath;
|
use reflexo::ImmutPath;
|
||||||
use reflexo_typst::{vfs::FileId, SourceWorld, TypstDocument, TypstHtmlDocument};
|
use reflexo_typst::{vfs::FileId, TypstDocument, TypstHtmlDocument};
|
||||||
use tinymist_debug::CoverageResult;
|
use tinymist_debug::CoverageResult;
|
||||||
use tinymist_project::world::{system::print_diagnostics, DiagnosticFormat};
|
use tinymist_project::world::{system::print_diagnostics, DiagnosticFormat};
|
||||||
use tinymist_query::analysis::Analysis;
|
use tinymist_query::analysis::Analysis;
|
||||||
use tinymist_query::syntax::{cast_include_expr, find_source_by_expr, node_ancestors};
|
use tinymist_query::syntax::{cast_include_expr, find_source_by_expr, node_ancestors};
|
||||||
use tinymist_query::testing::{TestCaseKind, TestSuites};
|
use tinymist_query::testing::{TestCaseKind, TestSuites};
|
||||||
use tinymist_std::{bail, error::prelude::*, fs::paths::write_atomic, typst::TypstPagedDocument};
|
use tinymist_std::{bail, error::prelude::*, fs::paths::write_atomic, typst::TypstPagedDocument};
|
||||||
use typst::diag::SourceDiagnostic;
|
use typst::diag::{Severity, SourceDiagnostic};
|
||||||
use typst::ecow::EcoVec;
|
use typst::ecow::EcoVec;
|
||||||
use typst::foundations::{Context, Label};
|
use typst::foundations::{Context, Label};
|
||||||
use typst::syntax::{ast, LinkedNode, Source, Span};
|
use typst::syntax::{ast, LinkedNode, Source, Span};
|
||||||
|
@ -25,7 +25,7 @@ use typst::{utils::PicoStr, World};
|
||||||
use typst_shim::eval::TypstEngine;
|
use typst_shim::eval::TypstEngine;
|
||||||
|
|
||||||
use super::project::{start_project, StartProjectResult};
|
use super::project::{start_project, StartProjectResult};
|
||||||
use crate::world::with_main;
|
use crate::world::{with_main, SourceWorld};
|
||||||
use crate::{project::*, utils::exit_on_ctrl_c};
|
use crate::{project::*, utils::exit_on_ctrl_c};
|
||||||
|
|
||||||
const TEST_EVICT_MAX_AGE: usize = 30;
|
const TEST_EVICT_MAX_AGE: usize = 30;
|
||||||
|
@ -239,7 +239,7 @@ fn test_once(world: &LspWorld, ctx: &TestContext) -> Result<bool> {
|
||||||
let result = if ctx.args.coverage {
|
let result = if ctx.args.coverage {
|
||||||
let (cov, result) = tinymist_debug::with_cov(world, |world| {
|
let (cov, result) = tinymist_debug::with_cov(world, |world| {
|
||||||
let suites = suites.recheck(world);
|
let suites = suites.recheck(world);
|
||||||
let runner = TestRunner::new(ctx, &world, &suites);
|
let runner = TestRunner::new(ctx, world, &suites);
|
||||||
let result = print_diag_or_error(world, runner.run());
|
let result = print_diag_or_error(world, runner.run());
|
||||||
comemo::evict(TEST_EVICT_MAX_AGE);
|
comemo::evict(TEST_EVICT_MAX_AGE);
|
||||||
result
|
result
|
||||||
|
@ -248,7 +248,7 @@ fn test_once(world: &LspWorld, ctx: &TestContext) -> Result<bool> {
|
||||||
result
|
result
|
||||||
} else {
|
} else {
|
||||||
let suites = suites.recheck(world);
|
let suites = suites.recheck(world);
|
||||||
let runner = TestRunner::new(ctx, &world, &suites);
|
let runner = TestRunner::new(ctx, world, &suites);
|
||||||
comemo::evict(TEST_EVICT_MAX_AGE);
|
comemo::evict(TEST_EVICT_MAX_AGE);
|
||||||
runner.run()
|
runner.run()
|
||||||
};
|
};
|
||||||
|
@ -294,7 +294,7 @@ impl TestContext {
|
||||||
|
|
||||||
struct TestRunner<'a> {
|
struct TestRunner<'a> {
|
||||||
ctx: &'a TestContext,
|
ctx: &'a TestContext,
|
||||||
world: &'a dyn World,
|
world: &'a dyn SourceWorld,
|
||||||
suites: &'a TestSuites,
|
suites: &'a TestSuites,
|
||||||
diagnostics: Mutex<Vec<EcoVec<SourceDiagnostic>>>,
|
diagnostics: Mutex<Vec<EcoVec<SourceDiagnostic>>>,
|
||||||
examples: Mutex<HashSet<String>>,
|
examples: Mutex<HashSet<String>>,
|
||||||
|
@ -302,7 +302,7 @@ struct TestRunner<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TestRunner<'a> {
|
impl<'a> TestRunner<'a> {
|
||||||
fn new(ctx: &'a TestContext, world: &'a dyn World, suites: &'a TestSuites) -> Self {
|
fn new(ctx: &'a TestContext, world: &'a dyn SourceWorld, suites: &'a TestSuites) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
world,
|
world,
|
||||||
|
@ -366,7 +366,7 @@ impl<'a> TestRunner<'a> {
|
||||||
let name = &test.name;
|
let name = &test.name;
|
||||||
let func = &test.function;
|
let func = &test.function;
|
||||||
|
|
||||||
let world = with_main(self.world, test.location);
|
let world = with_main(self.world.as_world(), test.location);
|
||||||
let mut engine = TypstEngine::new(&world);
|
let mut engine = TypstEngine::new(&world);
|
||||||
|
|
||||||
// Executes the function
|
// Executes the function
|
||||||
|
@ -409,7 +409,15 @@ impl<'a> TestRunner<'a> {
|
||||||
{
|
{
|
||||||
let diagnostics = self.diagnostics.into_inner();
|
let diagnostics = self.diagnostics.into_inner();
|
||||||
if !diagnostics.is_empty() {
|
if !diagnostics.is_empty() {
|
||||||
Err(diagnostics.into_iter().flatten().collect::<EcoVec<_>>())?
|
let diagnostics = diagnostics.into_iter().flatten().collect::<EcoVec<_>>();
|
||||||
|
let any_error = diagnostics.iter().any(|d| d.severity == Severity::Error);
|
||||||
|
|
||||||
|
if any_error {
|
||||||
|
Err(diagnostics)?
|
||||||
|
} else {
|
||||||
|
print_diagnostics(self.world, diagnostics.iter(), DiagnosticFormat::Human)
|
||||||
|
.context_ut("print diagnostics")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(!self.failed.load(std::sync::atomic::Ordering::SeqCst))
|
Ok(!self.failed.load(std::sync::atomic::Ordering::SeqCst))
|
||||||
|
@ -425,7 +433,7 @@ impl<'a> TestRunner<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let world = with_main(self.world, test.id());
|
let world = with_main(self.world.as_world(), test.id());
|
||||||
let mut has_err = false;
|
let mut has_err = false;
|
||||||
let (has_err_, doc) = self.build_example::<TypstPagedDocument>(&world);
|
let (has_err_, doc) = self.build_example::<TypstPagedDocument>(&world);
|
||||||
has_err |= has_err_ || self.render_paged(name, doc.as_ref());
|
has_err |= has_err_ || self.render_paged(name, doc.as_ref());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue