mirror of
https://github.com/HigherOrderCO/Kind1.git
synced 2024-07-14 15:10:32 +03:00
feat: Move running kind inside a session to kind-driver
This commit is contained in:
parent
2d0cda4faa
commit
0fdcff3a11
@ -1,14 +1,12 @@
|
||||
#![feature(panic_info_message)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
use std::{fmt, io};
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use driver::resolution::ResolutionError;
|
||||
use kind_driver::session::Session;
|
||||
|
||||
use kind_report::data::{Diagnostic, FileCache, Log, Severity};
|
||||
use kind_report::data::{FileCache, Log};
|
||||
use kind_report::RenderConfig;
|
||||
use std::panic;
|
||||
|
||||
@ -143,7 +141,7 @@ where
|
||||
pub fn render_to_stderr<T, E>(render_config: &RenderConfig, session: &T, err: &E)
|
||||
where
|
||||
T: FileCache,
|
||||
E: Report,
|
||||
E: Report + ?Sized,
|
||||
{
|
||||
Report::render(
|
||||
err,
|
||||
@ -154,77 +152,16 @@ where
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn compile_in_session<T>(
|
||||
pub fn run_in_session<T>(
|
||||
render_config: &RenderConfig,
|
||||
root: PathBuf,
|
||||
file: String,
|
||||
compiled: bool,
|
||||
fun: &mut dyn FnMut(&mut Session) -> anyhow::Result<T>,
|
||||
action: &mut dyn FnMut(&mut Session) -> anyhow::Result<T>,
|
||||
) -> anyhow::Result<T> {
|
||||
let (rx, tx) = std::sync::mpsc::channel();
|
||||
|
||||
let mut session = Session::new(root, rx);
|
||||
|
||||
eprintln!();
|
||||
|
||||
render_to_stderr(
|
||||
render_config,
|
||||
&session,
|
||||
&Log::Checking(format!("The file '{}'", file)),
|
||||
);
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let res = fun(&mut session);
|
||||
|
||||
let diagnostics = tx.try_iter().collect::<Vec<Box<dyn Diagnostic>>>();
|
||||
|
||||
let mut contains_error = false;
|
||||
|
||||
let mut hidden = 0;
|
||||
let total = diagnostics.len() as u64;
|
||||
|
||||
for diagnostic in diagnostics {
|
||||
if diagnostic.get_severity() == Severity::Error {
|
||||
contains_error = true;
|
||||
}
|
||||
|
||||
let is_root = diagnostic
|
||||
.get_syntax_ctx()
|
||||
.map(|x| x.is_root())
|
||||
.unwrap_or_default();
|
||||
|
||||
if render_config.only_main && !is_root {
|
||||
hidden += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
render_to_stderr(render_config, &session, &diagnostic)
|
||||
}
|
||||
|
||||
if !contains_error {
|
||||
render_to_stderr(
|
||||
render_config,
|
||||
&session,
|
||||
&if compiled {
|
||||
Log::Compiled(start.elapsed())
|
||||
} else {
|
||||
Log::Checked(start.elapsed())
|
||||
},
|
||||
);
|
||||
|
||||
eprintln!();
|
||||
|
||||
res
|
||||
} else {
|
||||
render_to_stderr(render_config, &session, &Log::Failed(start.elapsed(), total, hidden));
|
||||
eprintln!();
|
||||
|
||||
match res {
|
||||
Ok(_) => Err(ResolutionError.into()),
|
||||
Err(res) => Err(res),
|
||||
}
|
||||
}
|
||||
let log =
|
||||
|session: &Session, report: &dyn Report| render_to_stderr(render_config, session, report);
|
||||
driver::run_in_session(render_config, root, file, compiled, action, &log)
|
||||
}
|
||||
|
||||
pub fn run_cli(config: Cli) -> anyhow::Result<()> {
|
||||
@ -254,7 +191,7 @@ pub fn run_cli(config: Cli) -> anyhow::Result<()> {
|
||||
|
||||
match config.command {
|
||||
Command::Check { file, coverage } => {
|
||||
compile_in_session(&render_config, root, file.clone(), false, &mut |session| {
|
||||
run_in_session(&render_config, root, file.clone(), false, &mut |session| {
|
||||
let (_, rewrites) = driver::type_check_book(
|
||||
session,
|
||||
&PathBuf::from(file.clone()),
|
||||
@ -270,7 +207,7 @@ pub fn run_cli(config: Cli) -> anyhow::Result<()> {
|
||||
}
|
||||
Command::ToHVM { file } => {
|
||||
let result =
|
||||
compile_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
run_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
let book = driver::erase_book(
|
||||
session,
|
||||
&PathBuf::from(file.clone()),
|
||||
@ -282,22 +219,21 @@ pub fn run_cli(config: Cli) -> anyhow::Result<()> {
|
||||
println!("{}", result);
|
||||
}
|
||||
Command::Run { file } => {
|
||||
let res =
|
||||
compile_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
let path = PathBuf::from(file.clone());
|
||||
let book = driver::erase_book(session, &path, entrypoints.clone())?;
|
||||
driver::check_main_entry(session, &book)?;
|
||||
let book = driver::compile_book_to_hvm(book, config.trace);
|
||||
let (result, rewrites) = driver::execute_file(&book.to_string(), config.tids)?;
|
||||
let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
let path = PathBuf::from(file.clone());
|
||||
let book = driver::erase_book(session, &path, entrypoints.clone())?;
|
||||
driver::check_main_entry(session, &book)?;
|
||||
let book = driver::compile_book_to_hvm(book, config.trace);
|
||||
let (result, rewrites) = driver::execute_file(&book.to_string(), config.tids)?;
|
||||
|
||||
render_to_stderr(&render_config, session, &Log::Rewrites(rewrites));
|
||||
render_to_stderr(&render_config, session, &Log::Rewrites(rewrites));
|
||||
|
||||
Ok(result)
|
||||
})?;
|
||||
Ok(result)
|
||||
})?;
|
||||
println!("{}", res);
|
||||
}
|
||||
Command::Show { file } => {
|
||||
compile_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
run_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::to_book(session, &PathBuf::from(file.clone()))
|
||||
})
|
||||
.map(|res| {
|
||||
@ -306,49 +242,44 @@ pub fn run_cli(config: Cli) -> anyhow::Result<()> {
|
||||
})?;
|
||||
}
|
||||
Command::ToKindCore { file } => {
|
||||
let res =
|
||||
compile_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::desugar_book(session, &PathBuf::from(file.clone()))
|
||||
})?;
|
||||
let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::desugar_book(session, &PathBuf::from(file.clone()))
|
||||
})?;
|
||||
print!("{}", res);
|
||||
}
|
||||
Command::Erase { file } => {
|
||||
let res =
|
||||
compile_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone())
|
||||
})?;
|
||||
let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone())
|
||||
})?;
|
||||
print!("{}", res);
|
||||
}
|
||||
Command::GenChecker { file, coverage } => {
|
||||
let res =
|
||||
compile_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::check_erasure_book(session, &PathBuf::from(file.clone()))
|
||||
})?;
|
||||
let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::check_erasure_book(session, &PathBuf::from(file.clone()))
|
||||
})?;
|
||||
print!("{}", driver::generate_checker(&res, coverage));
|
||||
}
|
||||
Command::Eval { file } => {
|
||||
let res =
|
||||
compile_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
let book = driver::desugar_book(session, &PathBuf::from(file.clone()))?;
|
||||
driver::check_main_desugared_entry(session, &book)?;
|
||||
let (res, rewrites) = driver::eval_in_checker(&book);
|
||||
let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
let book = driver::desugar_book(session, &PathBuf::from(file.clone()))?;
|
||||
driver::check_main_desugared_entry(session, &book)?;
|
||||
let (res, rewrites) = driver::eval_in_checker(&book);
|
||||
|
||||
render_to_stderr(&render_config, session, &Log::Rewrites(rewrites));
|
||||
render_to_stderr(&render_config, session, &Log::Rewrites(rewrites));
|
||||
|
||||
Ok(res)
|
||||
})?;
|
||||
Ok(res)
|
||||
})?;
|
||||
println!("{}", res);
|
||||
}
|
||||
Command::ToKDL { file, namespace } => {
|
||||
let res =
|
||||
compile_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::compile_book_to_kdl(
|
||||
&PathBuf::from(file.clone()),
|
||||
session,
|
||||
&namespace.clone().unwrap_or("".to_string()),
|
||||
entrypoints.clone(),
|
||||
)
|
||||
})?;
|
||||
let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::compile_book_to_kdl(
|
||||
&PathBuf::from(file.clone()),
|
||||
session,
|
||||
&namespace.clone().unwrap_or("".to_string()),
|
||||
entrypoints.clone(),
|
||||
)
|
||||
})?;
|
||||
println!("{}", res);
|
||||
}
|
||||
}
|
||||
@ -357,9 +288,12 @@ pub fn run_cli(config: Cli) -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
||||
panic::set_hook(Box::new(|e| {
|
||||
println!("\n[Error]: internal compiler error '{:?}' at {}", e.message().unwrap(), e.location().unwrap());
|
||||
println!(
|
||||
"\n[Error]: internal compiler error '{:?}' at {}",
|
||||
e.message().unwrap(),
|
||||
e.location().unwrap()
|
||||
);
|
||||
println!("Please submit a full report about this error at: https://github.com/HigherOrderCO/Kind/issues/new");
|
||||
println!("It would help us a lot :)\n");
|
||||
}));
|
||||
|
@ -1,14 +1,18 @@
|
||||
use checker::eval;
|
||||
use diagnostic::{DriverDiagnostic, GenericDriverError};
|
||||
use kind_pass::{desugar, erasure, inline::inline_book};
|
||||
use kind_report::data::FileCache;
|
||||
use kind_report::{
|
||||
data::{FileCache, Log, Severity},
|
||||
report::Report,
|
||||
RenderConfig,
|
||||
};
|
||||
use kind_span::SyntaxCtxIndex;
|
||||
|
||||
use hvm::language::{syntax as backend};
|
||||
use hvm::language::syntax as backend;
|
||||
use kind_tree::{concrete, desugared, untyped};
|
||||
use resolution::ResolutionError;
|
||||
use session::Session;
|
||||
use std::{path::PathBuf};
|
||||
use std::{path::PathBuf, time::Instant};
|
||||
|
||||
use kind_checker as checker;
|
||||
|
||||
@ -147,9 +151,7 @@ pub fn check_main_desugared_entry(
|
||||
|
||||
pub fn execute_file(file: &str, tids: Option<usize>) -> anyhow::Result<(String, u64)> {
|
||||
match eval(file, "Main", false, tids) {
|
||||
Ok((res, rewrites)) => {
|
||||
Ok((res.to_string(), rewrites))
|
||||
},
|
||||
Ok((res, rewrites)) => Ok((res.to_string(), rewrites)),
|
||||
Err(_) => anyhow::Result::Err(GenericDriverError.into()),
|
||||
}
|
||||
}
|
||||
@ -161,3 +163,69 @@ pub fn eval_in_checker(book: &desugared::Book) -> (String, u64) {
|
||||
pub fn generate_checker(book: &desugared::Book, check_coverage: bool) -> String {
|
||||
checker::gen_checker(book, check_coverage, book.entrs.keys().cloned().collect())
|
||||
}
|
||||
|
||||
pub fn run_in_session<T>(
|
||||
render_config: &RenderConfig,
|
||||
root: PathBuf,
|
||||
file: String,
|
||||
compiled: bool,
|
||||
action: &mut dyn FnMut(&mut Session) -> anyhow::Result<T>,
|
||||
log: &dyn Fn(&Session, &dyn Report),
|
||||
) -> anyhow::Result<T> {
|
||||
let (rx, tx) = std::sync::mpsc::channel();
|
||||
|
||||
let mut session = Session::new(root, rx);
|
||||
|
||||
log(&session, &Log::Empty);
|
||||
log(&session, &Log::Checking(format!("The file '{}'", file)));
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let res = action(&mut session);
|
||||
|
||||
let diagnostics = tx.try_iter().collect::<Vec<_>>();
|
||||
|
||||
let mut contains_error = false;
|
||||
|
||||
let mut hidden = 0;
|
||||
let total = diagnostics.len() as u64;
|
||||
|
||||
for diagnostic in diagnostics {
|
||||
if diagnostic.get_severity() == Severity::Error {
|
||||
contains_error = true;
|
||||
}
|
||||
|
||||
let is_root = diagnostic
|
||||
.get_syntax_ctx()
|
||||
.map(|x| x.is_root())
|
||||
.unwrap_or_default();
|
||||
|
||||
if render_config.only_main && !is_root {
|
||||
hidden += 1;
|
||||
continue;
|
||||
}
|
||||
log(&session, &diagnostic);
|
||||
}
|
||||
|
||||
if !contains_error {
|
||||
log(
|
||||
&session,
|
||||
&if compiled {
|
||||
Log::Compiled(start.elapsed())
|
||||
} else {
|
||||
Log::Checked(start.elapsed())
|
||||
},
|
||||
);
|
||||
log(&session, &Log::Empty);
|
||||
|
||||
res
|
||||
} else {
|
||||
log(&session, &Log::Failed(start.elapsed(), total, hidden));
|
||||
log(&session, &Log::Empty);
|
||||
|
||||
match res {
|
||||
Ok(_) => Err(ResolutionError.into()),
|
||||
Err(res) => Err(res),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ pub enum Log {
|
||||
Compiled(Duration),
|
||||
Rewrites(u64),
|
||||
Failed(Duration, u64, u64),
|
||||
Empty,
|
||||
}
|
||||
|
||||
pub trait Diagnostic {
|
||||
|
@ -11,11 +11,11 @@ use std::fmt::Write;
|
||||
use std::path::PathBuf;
|
||||
use yansi::Paint;
|
||||
|
||||
fn colorize_code<T: Write + Sized>(
|
||||
fn colorize_code(
|
||||
markers: &mut [&(Point, Point, &Marker)],
|
||||
code_line: &str,
|
||||
modify: &dyn Fn(&str) -> String,
|
||||
fmt: &mut T,
|
||||
fmt: &mut dyn Write,
|
||||
) -> std::fmt::Result {
|
||||
markers.sort_by(|x, y| x.0.column.cmp(&y.0.column));
|
||||
let mut start = 0;
|
||||
@ -47,12 +47,12 @@ fn colorize_code<T: Write + Sized>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mark_inlined<T: Write + Sized>(
|
||||
fn mark_inlined(
|
||||
prefix: &str,
|
||||
code: &str,
|
||||
config: &RenderConfig,
|
||||
inline_markers: &mut [&(Point, Point, &Marker)],
|
||||
fmt: &mut T,
|
||||
fmt: &mut dyn Write,
|
||||
) -> std::fmt::Result {
|
||||
inline_markers.sort_by(|x, y| x.0.column.cmp(&y.0.column));
|
||||
let mut start = 0;
|
||||
@ -148,7 +148,7 @@ impl Color {
|
||||
}
|
||||
|
||||
impl Renderable<Classic> for Severity {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
use Severity::*;
|
||||
|
||||
let painted = match self {
|
||||
@ -162,7 +162,7 @@ impl Renderable<Classic> for Severity {
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Classic> for Header<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
Renderable::<Classic>::render(self.severity, fmt, cache, config)?;
|
||||
fmt.write_str(&Paint::new(&self.title).bold().to_string())?;
|
||||
fmt.write_char('\n')
|
||||
@ -170,7 +170,7 @@ impl<'a> Renderable<Classic> for Header<'a> {
|
||||
}
|
||||
|
||||
impl Renderable<Classic> for Subtitle {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
match self {
|
||||
Subtitle::Normal(color, phr) | Subtitle::Field(color, phr) => {
|
||||
let bullet = color.colorize(config.chars.bullet);
|
||||
@ -194,7 +194,7 @@ impl Renderable<Classic> for Subtitle {
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Classic> for Word {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
match self {
|
||||
Word::Normal(str) => write!(fmt, "{} ", Paint::new(str)),
|
||||
Word::Dimmed(str) => write!(fmt, "{} ", Paint::new(str).dimmed()),
|
||||
@ -205,7 +205,7 @@ impl<'a> Renderable<Classic> for Word {
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Classic> for Subtitles<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
if !self.0.is_empty() {
|
||||
writeln!(fmt)?;
|
||||
}
|
||||
@ -215,7 +215,7 @@ impl<'a> Renderable<Classic> for Subtitles<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Classic> for CodeBlock<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
let guide = LineGuide::get(self.code);
|
||||
let point = guide.find(self.markers.0[0].position.start);
|
||||
|
||||
@ -342,7 +342,7 @@ impl<'a> Renderable<Classic> for CodeBlock<'a> {
|
||||
}
|
||||
|
||||
impl Renderable<Classic> for Log {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
match self {
|
||||
Log::Checking(file) => {
|
||||
writeln!(
|
||||
@ -390,12 +390,13 @@ impl Renderable<Classic> for Log {
|
||||
u64
|
||||
)
|
||||
}
|
||||
Log::Empty => writeln!(fmt, ""),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Classic> for Markers<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
let groups = group_markers(&self.0);
|
||||
let is_empty = groups.is_empty();
|
||||
let current = PathBuf::from(".").canonicalize().unwrap();
|
||||
@ -424,7 +425,7 @@ impl<'a> Renderable<Classic> for Markers<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Classic> for Hints<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
for hint in self.0 {
|
||||
writeln!(
|
||||
fmt,
|
||||
@ -440,7 +441,7 @@ impl<'a> Renderable<Classic> for Hints<'a> {
|
||||
}
|
||||
|
||||
impl Renderable<Classic> for DiagnosticFrame {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
write!(fmt, " ")?;
|
||||
|
||||
Renderable::<Classic>::render(&self.header(), fmt, cache, config)?;
|
||||
|
@ -7,10 +7,10 @@ use crate::{report::*, RenderConfig};
|
||||
|
||||
use super::{CodeBlock, Compact, Renderable, Res};
|
||||
|
||||
fn mark_code<T: Write + Sized>(
|
||||
fn mark_code(
|
||||
markers: &mut [&(Point, Point, &Marker)],
|
||||
code_line: &str,
|
||||
fmt: &mut T,
|
||||
fmt: &mut dyn Write,
|
||||
) -> std::fmt::Result {
|
||||
markers.sort_by(|x, y| x.0.column.cmp(&y.0.column));
|
||||
let mut start = 0;
|
||||
@ -42,7 +42,7 @@ fn mark_code<T: Write + Sized>(
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Compact> for Word {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
match self {
|
||||
Word::Normal(str) => write!(fmt, "{} ", str),
|
||||
Word::Dimmed(str) => write!(fmt, "{} ", str),
|
||||
@ -53,7 +53,7 @@ impl<'a> Renderable<Compact> for Word {
|
||||
}
|
||||
|
||||
impl Renderable<Compact> for Subtitle {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
match self {
|
||||
Subtitle::Field(_, phr) => writeln!(fmt, "{}", phr.to_lowercase()),
|
||||
Subtitle::Normal(_, phr) => writeln!(fmt, "- {}", phr),
|
||||
@ -69,7 +69,7 @@ impl Renderable<Compact> for Subtitle {
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Compact> for Subtitles<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
if !self.0.is_empty() {
|
||||
writeln!(fmt)?;
|
||||
}
|
||||
@ -79,7 +79,7 @@ impl<'a> Renderable<Compact> for Subtitles<'a> {
|
||||
}
|
||||
|
||||
impl Renderable<Compact> for Severity {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
use Severity::*;
|
||||
|
||||
let painted = match self {
|
||||
@ -93,13 +93,13 @@ impl Renderable<Compact> for Severity {
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Compact> for Header<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
writeln!(fmt, "{}", &self.title.to_lowercase())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Compact> for CodeBlock<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _8778: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
writeln!(fmt, "location")?;
|
||||
let guide = LineGuide::get(self.code);
|
||||
|
||||
@ -133,7 +133,7 @@ impl<'a> Renderable<Compact> for CodeBlock<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Renderable<Compact> for Markers<'a> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
let groups = group_markers(&self.0);
|
||||
let current = PathBuf::from(".").canonicalize().unwrap();
|
||||
|
||||
@ -155,12 +155,7 @@ impl<'a> Renderable<Compact> for Markers<'a> {
|
||||
}
|
||||
|
||||
impl Renderable<Compact> for DiagnosticFrame {
|
||||
fn render<U: std::fmt::Write, C: crate::data::FileCache>(
|
||||
&self,
|
||||
fmt: &mut U,
|
||||
cache: &C,
|
||||
config: &crate::RenderConfig,
|
||||
) -> super::Res {
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
Renderable::<Compact>::render(&self.header(), fmt, cache, config)?;
|
||||
Renderable::<Compact>::render(&self.subtitles(), fmt, cache, config)?;
|
||||
Renderable::<Compact>::render(&self.markers(), fmt, cache, config)?;
|
||||
@ -170,7 +165,7 @@ impl Renderable<Compact> for DiagnosticFrame {
|
||||
}
|
||||
|
||||
impl Renderable<Compact> for Log {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
|
||||
fn render(&self, fmt: &mut dyn Write, _: &dyn FileCache, _: &RenderConfig) -> Res {
|
||||
match self {
|
||||
Log::Compiled(_) => writeln!(fmt, "compiled"),
|
||||
Log::Checked(_) => writeln!(fmt, "checked"),
|
||||
|
@ -1,7 +1,10 @@
|
||||
use std::{fmt::Write, path::Path};
|
||||
|
||||
use crate::{data::{FileCache, Diagnostic, DiagnosticFrame, Log}, RenderConfig};
|
||||
use super::code::FileMarkers;
|
||||
use crate::{
|
||||
data::{Diagnostic, DiagnosticFrame, FileCache, Log},
|
||||
RenderConfig,
|
||||
};
|
||||
|
||||
pub mod classic;
|
||||
pub mod compact;
|
||||
@ -35,17 +38,20 @@ pub enum Mode {
|
||||
pub(crate) struct CodeBlock<'a> {
|
||||
pub code: &'a str,
|
||||
pub path: &'a Path,
|
||||
pub markers: &'a FileMarkers
|
||||
pub markers: &'a FileMarkers,
|
||||
}
|
||||
|
||||
/// A type class for renderable error reports and messages. It's useful
|
||||
/// to change easily things without problems.
|
||||
pub trait Renderable<T> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res;
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res;
|
||||
}
|
||||
|
||||
impl<'a, T, E> Renderable<T> for Vec<E> where E : Renderable<T> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
impl<'a, T, E> Renderable<T> for Vec<E>
|
||||
where
|
||||
E: Renderable<T>,
|
||||
{
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
for elem in self {
|
||||
elem.render(fmt, cache, config)?;
|
||||
}
|
||||
@ -53,14 +59,20 @@ impl<'a, T, E> Renderable<T> for Vec<E> where E : Renderable<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Renderable<T> for Box<dyn Diagnostic> where DiagnosticFrame: Renderable<T> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
impl<T> Renderable<T> for Box<dyn Diagnostic>
|
||||
where
|
||||
DiagnosticFrame: Renderable<T>,
|
||||
{
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
Renderable::<T>::render(&self.to_diagnostic_frame(config), fmt, cache, config)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Report where Self : Renderable<Classic> + Renderable<Compact> {
|
||||
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
|
||||
pub trait Report
|
||||
where
|
||||
Self: Renderable<Classic> + Renderable<Compact>,
|
||||
{
|
||||
fn render(&self, fmt: &mut dyn Write, cache: &dyn FileCache, config: &RenderConfig) -> Res {
|
||||
match config.mode {
|
||||
Mode::Classic => Renderable::<Classic>::render(self, fmt, cache, config),
|
||||
Mode::Compact => Renderable::<Compact>::render(self, fmt, cache, config),
|
||||
@ -69,4 +81,4 @@ pub trait Report where Self : Renderable<Classic> + Renderable<Compact> {
|
||||
}
|
||||
|
||||
impl Report for Box<dyn Diagnostic> {}
|
||||
impl Report for Log {}
|
||||
impl Report for Log {}
|
||||
|
Loading…
Reference in New Issue
Block a user