feat: pass tests if warnings happens (#1535)

This commit is contained in:
Myriad-Dreamin 2025-03-19 12:02:40 +08:00 committed by GitHub
parent 4bb16b5b93
commit c8c891fbc3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 61 additions and 51 deletions

1
.gitignore vendored
View file

@ -12,3 +12,4 @@ editors/lapce/out/
*.pdf
.vscode/*.code-workspace
refs/

View file

@ -66,6 +66,10 @@ where
}
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> {
self.base.path_for_id(id)
}

View file

@ -7,5 +7,5 @@ pub use tinymist_world::entry::*;
pub use tinymist_world::{font, package, system, vfs};
pub use tinymist_world::{
with_main, CompilerUniverse, CompilerWorld, DiagnosticFormat, EntryOpts, EntryState,
RevisingUniverse, TaskInputs,
RevisingUniverse, SourceWorld, TaskInputs,
};

View file

@ -11,9 +11,9 @@ use tinymist_std::Result;
use tinymist_vfs::FileId;
use typst::diag::{eco_format, Severity, SourceDiagnostic};
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.
fn color_stream() -> StandardStream {
@ -25,12 +25,12 @@ fn color_stream() -> StandardStream {
}
/// Print diagnostic messages to the terminal.
pub fn print_diagnostics<'d, 'files, W: SourceWorld>(
world: &'files W,
pub fn print_diagnostics<'d, 'files>(
world: &'files dyn SourceWorld,
errors: impl Iterator<Item = &'d SourceDiagnostic>,
diagnostic_format: DiagnosticFormat,
) -> Result<(), codespan_reporting::files::Error> {
let world = world.for_codespan_reporting();
let world = CodeSpanReportWorld::new(world);
let mut w = match diagnostic_format {
DiagnosticFormat::Human => color_stream(),
@ -77,6 +77,6 @@ pub fn print_diagnostics<'d, 'files, W: SourceWorld>(
}
/// 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)?))
}

View file

@ -772,43 +772,37 @@ impl typst::World for WorldWithMain<'_> {
}
pub trait SourceWorld: World {
fn as_world(&self) -> &dyn World;
fn path_for_id(&self, id: FileId) -> Result<PathResolution, FileError>;
fn lookup(&self, id: FileId) -> Source {
self.source(id)
.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> {
fn as_world(&self) -> &dyn World {
self
}
/// Resolve the real path for a file id.
fn path_for_id(&self, id: FileId) -> Result<PathResolution, FileError> {
self.path_for_id(id)
}
}
pub struct CodeSpanReportWorld<'a, T> {
pub world: &'a T,
pub struct CodeSpanReportWorld<'a> {
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
/// for rendering `diagnostic::Label`s in the corresponding source files.
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`].
fn line_range(&'a self, id: FileId, given: usize) -> CodespanResult<std::ops::Range<usize>> {
self.world.map_source_or_default(id, 0..0, |source| {
source
.line_to_range(given)
.ok_or_else(|| CodespanError::LineTooLarge {
given,
max: source.len_lines(),
})
})
match self.world.source(id).ok() {
Some(source) => {
source
.line_to_range(given)
.ok_or_else(|| CodespanError::LineTooLarge {
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.
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.
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`].
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`].
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`].
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)
}
}

View file

@ -10,14 +10,14 @@ use itertools::Either;
use parking_lot::Mutex;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use reflexo::ImmutPath;
use reflexo_typst::{vfs::FileId, SourceWorld, TypstDocument, TypstHtmlDocument};
use reflexo_typst::{vfs::FileId, TypstDocument, TypstHtmlDocument};
use tinymist_debug::CoverageResult;
use tinymist_project::world::{system::print_diagnostics, DiagnosticFormat};
use tinymist_query::analysis::Analysis;
use tinymist_query::syntax::{cast_include_expr, find_source_by_expr, node_ancestors};
use tinymist_query::testing::{TestCaseKind, TestSuites};
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::foundations::{Context, Label};
use typst::syntax::{ast, LinkedNode, Source, Span};
@ -25,7 +25,7 @@ use typst::{utils::PicoStr, World};
use typst_shim::eval::TypstEngine;
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};
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 (cov, result) = tinymist_debug::with_cov(world, |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());
comemo::evict(TEST_EVICT_MAX_AGE);
result
@ -248,7 +248,7 @@ fn test_once(world: &LspWorld, ctx: &TestContext) -> Result<bool> {
result
} else {
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);
runner.run()
};
@ -294,7 +294,7 @@ impl TestContext {
struct TestRunner<'a> {
ctx: &'a TestContext,
world: &'a dyn World,
world: &'a dyn SourceWorld,
suites: &'a TestSuites,
diagnostics: Mutex<Vec<EcoVec<SourceDiagnostic>>>,
examples: Mutex<HashSet<String>>,
@ -302,7 +302,7 @@ struct 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 {
ctx,
world,
@ -366,7 +366,7 @@ impl<'a> TestRunner<'a> {
let name = &test.name;
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);
// Executes the function
@ -409,7 +409,15 @@ impl<'a> TestRunner<'a> {
{
let diagnostics = self.diagnostics.into_inner();
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))
@ -425,7 +433,7 @@ impl<'a> TestRunner<'a> {
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 (has_err_, doc) = self.build_example::<TypstPagedDocument>(&world);
has_err |= has_err_ || self.render_paged(name, doc.as_ref());