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