feat: another mode for compact error messages

This commit is contained in:
Sofia R 2023-04-30 00:24:20 -03:00
parent b20c8eac68
commit d184e30701
24 changed files with 441 additions and 176 deletions

View File

@ -1,6 +1,9 @@
//! Errors created by the type checker.
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity, Subtitle, Word};
use kind_report::{
data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity, Subtitle, Word},
RenderConfig,
};
use kind_span::Range;
use kind_tree::desugared::Expr;
@ -16,40 +19,43 @@ pub(crate) enum TypeDiagnostic {
Inspection(Context, Range, Box<Expr>),
TooManyArguments(Context, Range),
TypeMismatch(Context, Range, Box<Expr>, Box<Expr>),
UncoveredPattern(Context, Range, Vec<Box<Expr>>)
UncoveredPattern(Context, Range, Vec<Box<Expr>>),
}
fn context_to_subtitles(ctx: &Context, subtitles: &mut Vec<Subtitle>) {
fn context_to_subtitles(config: &RenderConfig, ctx: &Context, subtitles: &mut Vec<Subtitle>) {
subtitles.push(Subtitle::LineBreak);
if !ctx.0.is_empty() {
subtitles.push(Subtitle::Phrase(
Color::Snd,
vec![Word::White("Context:".to_string())],
));
subtitles.push(Subtitle::Field(Color::Snd, "Context".to_string()));
}
let biggest = ctx
.0
.iter()
.max_by_key(|p| p.0.len())
.map(|x| x.0.len())
.unwrap_or(0);
let biggest = if config.not_align {
0
} else {
ctx.0
.iter()
.max_by_key(|p| p.0.len())
.map(|x| x.0.len())
.unwrap_or(0)
};
for (name, typ, vals) in &ctx.0 {
subtitles.push(Subtitle::Phrase(
Color::Snd,
vec![
Word::Dimmed(" ".to_string()),
Word::White(format!("{:<width$} :", name, width = biggest)),
Word::Painted(Color::Snd, typ.to_string()),
],
));
if config.hide_vals {
continue;
}
for val in vals {
subtitles.push(Subtitle::Phrase(
Color::Snd,
vec![
Word::Dimmed(" ".to_string()),
Word::Dimmed(format!("{:<width$} =", name, width = biggest)),
Word::Dimmed(val.to_string()),
],
@ -73,7 +79,7 @@ impl Diagnostic for TypeDiagnostic {
}
}
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
fn to_diagnostic_frame(&self, config: &RenderConfig) -> DiagnosticFrame {
match self {
TypeDiagnostic::TypeMismatch(ctx, range, detected, expected) => {
let mut subtitles = vec![
@ -92,7 +98,7 @@ impl Diagnostic for TypeDiagnostic {
],
),
];
context_to_subtitles(ctx, &mut subtitles);
context_to_subtitles(config, ctx, &mut subtitles);
DiagnosticFrame {
code: 101,
severity: Severity::Error,
@ -112,17 +118,17 @@ impl Diagnostic for TypeDiagnostic {
let mut subtitles = vec![Subtitle::Phrase(
Color::Snd,
vec![
Word::White("Expected:".to_string()),
Word::White("Hole:".to_string()),
Word::Painted(Color::Snd, expected.to_string()),
],
)];
context_to_subtitles(ctx, &mut subtitles);
context_to_subtitles(config, ctx, &mut subtitles);
DiagnosticFrame {
code: 101,
severity: Severity::Info,
title: "Inspection.".to_string(),
title: "Inspection".to_string(),
subtitles,
hints: vec![],
positions: vec![Marker {
@ -199,9 +205,16 @@ impl Diagnostic for TypeDiagnostic {
Color::For,
vec![
Word::White("Missing case :".to_string()),
Word::Painted(Color::For, terms.iter().map(|x| format!("{}", x)).collect::<Vec<_>>().join(" ")),
Word::Painted(
Color::For,
terms
.iter()
.map(|x| format!("{}", x))
.collect::<Vec<_>>()
.join(" "),
),
],
),],
)],
hints: vec![],
positions: vec![Marker {
position: *range,

View File

@ -6,11 +6,14 @@ use clap::{Parser, Subcommand};
use driver::resolution::ResolutionError;
use kind_driver::session::Session;
use kind_report::data::{Diagnostic, Log, Severity, FileCache};
use kind_report::data::{Diagnostic, FileCache, Log, Severity};
use kind_report::RenderConfig;
use kind_driver as driver;
use kind_report::report::mode::{Renderable, Classic};
use kind_report::report::{Classic, Mode, Report};
pub type CO = Classic;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
@ -46,6 +49,14 @@ pub struct Cli {
#[arg(short, long)]
pub ascii: bool,
/// Compact error messages
#[arg(long)]
pub compact: bool,
/// Show values in error messages
#[arg(long)]
pub hide_vals: bool,
/// Entrypoint of the file that makes the erasure checker
/// not remove the entry.
#[arg(short, long)]
@ -88,7 +99,7 @@ pub enum Command {
GenChecker {
#[arg(short, long)]
coverage: bool,
file: String,
},
@ -122,12 +133,12 @@ where
}
}
pub fn render_to_stderr<C, T, E>(render_config: &RenderConfig, session: &T, err: &E)
pub fn render_to_stderr<T, E>(render_config: &RenderConfig, session: &T, err: &E)
where
T: FileCache,
E: Renderable<C>,
E: Report,
{
E::render(
Report::render(
err,
&mut ToWriteFmt(std::io::stderr()),
session,
@ -168,7 +179,7 @@ pub fn compile_in_session<T>(
contains_error = true;
}
render_to_stderr::<Classic, _, _>(render_config, &session, &diagnostic)
render_to_stderr(render_config, &session, &diagnostic)
}
if !contains_error {
@ -199,7 +210,13 @@ pub fn compile_in_session<T>(
pub fn run_cli(config: Cli) -> anyhow::Result<()> {
kind_report::check_if_colors_are_supported(config.no_color);
let render_config = kind_report::check_if_utf8_is_supported(config.ascii, 2);
let mode = if config.compact {
Mode::Compact
} else {
Mode::Classic
};
let render_config = kind_report::check_if_utf8_is_supported(config.ascii, 2, config.hide_vals, mode);
let root = config.root.unwrap_or_else(|| PathBuf::from("."));
let mut entrypoints = vec!["Main".to_string()];

View File

@ -1,4 +1,4 @@
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity};
use kind_report::{data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity}, RenderConfig};
use kind_span::Range;
pub(crate) enum DeriveDiagnostic {
@ -16,7 +16,7 @@ impl Diagnostic for DeriveDiagnostic {
}
}
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
fn to_diagnostic_frame(&self, _: &RenderConfig) -> DiagnosticFrame {
match self {
DeriveDiagnostic::CannotUseNamedVariable(range) => DiagnosticFrame {
code: 103,

View File

@ -3,7 +3,7 @@
use std::{path::PathBuf, fmt::Display, error::Error};
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity, Subtitle, Word};
use kind_report::{data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity, Subtitle, Word}, RenderConfig};
use kind_tree::symbol::{Ident, QualifiedIdent};
#[derive(Debug)]
@ -38,7 +38,7 @@ impl Diagnostic for DriverDiagnostic {
}
}
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
fn to_diagnostic_frame(&self, _: &RenderConfig) -> DiagnosticFrame {
match self {
DriverDiagnostic::UnboundVariable(idents, suggestions) => DiagnosticFrame {
code: 100,

View File

@ -1,7 +1,7 @@
//! All of the sintatic erros both from the
//! lexer and the parser.
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity};
use kind_report::{data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity}, RenderConfig};
use kind_span::{Range, SyntaxCtxIndex};
use crate::lexer::tokens::Token;
@ -67,7 +67,7 @@ impl Diagnostic for SyntaxDiagnostic {
}
}
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
fn to_diagnostic_frame(&self, _: &RenderConfig) -> DiagnosticFrame {
match self {
SyntaxDiagnostic::UnfinishedString(range) => DiagnosticFrame {
code: 1,

View File

@ -1,6 +1,6 @@
use std::{fmt::Display, error::Error};
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity};
use kind_report::{data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity}, RenderConfig};
use kind_span::{Range, SyntaxCtxIndex};
use kind_tree::symbol::Ident;
@ -96,7 +96,7 @@ impl Diagnostic for PassDiagnostic {
}
}
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
fn to_diagnostic_frame(&self, _: &RenderConfig) -> DiagnosticFrame {
match self {
PassDiagnostic::UnboundVariable(idents, suggestions) => DiagnosticFrame {
code: 100,

View File

@ -15,3 +15,4 @@ pathdiff = "0.2.1"
termsize = "0.1"
unicode-width = "0.1.10"
yansi = "0.5.1"
refl = "0.2.1"

View File

@ -1,7 +1,9 @@
use std::{time::Duration, path::PathBuf, ops::Sub};
use std::{time::Duration, path::PathBuf};
use kind_span::{Range, SyntaxCtxIndex};
use crate::RenderConfig;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Severity {
Error,
@ -28,6 +30,7 @@ pub enum Word {
#[derive(Debug, Clone)]
pub enum Subtitle {
Field(Color, String),
Normal(Color, String),
Bold(Color, String),
Phrase(Color, Vec<Word>),
@ -71,10 +74,16 @@ pub enum Log {
Rewrites(u64),
Failed(Duration),
}
pub struct DiagnosticConfig {
hide_vals: bool,
indent_ctx_vars: bool
}
pub trait Diagnostic {
fn get_syntax_ctx(&self) -> Option<SyntaxCtxIndex>;
fn get_severity(&self) -> Severity;
fn to_diagnostic_frame(&self) -> DiagnosticFrame;
fn to_diagnostic_frame(&self, config: &RenderConfig) -> DiagnosticFrame;
}
pub trait FileCache {

View File

@ -1,3 +1,4 @@
use report::Mode;
use yansi::Paint;
/// Data structures
@ -50,21 +51,39 @@ impl Chars {
pub struct RenderConfig<'a> {
pub chars: &'a Chars,
pub indent: usize,
pub hide_vals: bool,
pub mode: Mode,
pub not_align: bool,
}
impl<'a> RenderConfig<'a> {
pub fn unicode(indent: usize) -> RenderConfig<'a> {
pub fn unicode(indent: usize, hide_vals: bool) -> RenderConfig<'a> {
RenderConfig {
chars: Chars::unicode(),
indent,
hide_vals,
mode: Mode::Classic,
not_align: false,
}
}
pub fn ascii(indent: usize) -> RenderConfig<'a> {
pub fn ascii(indent: usize, hide_vals: bool) -> RenderConfig<'a> {
RenderConfig {
chars: Chars::ascii(),
indent,
hide_vals,
mode: Mode::Classic,
not_align: false,
}
}
pub fn compact(indent: usize) -> RenderConfig<'a> {
RenderConfig {
chars: Chars::ascii(),
indent,
hide_vals: true,
mode: Mode::Compact,
not_align: true,
}
}
}
@ -75,10 +94,15 @@ pub fn check_if_colors_are_supported(disable: bool) {
}
}
pub fn check_if_utf8_is_supported<'a>(disable: bool, indent: usize) -> RenderConfig<'a> {
if disable || (cfg!(windows) && !Paint::enable_windows_ascii()) {
RenderConfig::ascii(indent)
} else {
RenderConfig::unicode(indent)
pub fn check_if_utf8_is_supported<'a>(disable: bool, indent: usize, hide_vals: bool, mode: Mode) -> RenderConfig<'a> {
match mode {
Mode::Classic => {
if disable || (cfg!(windows) && !Paint::enable_windows_ascii()) {
RenderConfig::ascii(indent, hide_vals)
} else {
RenderConfig::unicode(indent, hide_vals)
}
},
Mode::Compact => RenderConfig::compact(0),
}
}

View File

@ -1,4 +1,4 @@
use fxhash::FxHashMap;
use fxhash::{FxHashMap, FxHashSet};
use kind_span::{Pos, SyntaxCtxIndex};
use std::{collections::hash_map::Iter, fmt::Display};
use unicode_width::UnicodeWidthStr;
@ -105,3 +105,53 @@ pub fn group_markers(markers: &[Marker]) -> SortedMarkers {
.collect(),
)
}
pub fn group_marker_lines<'a>(
guide: &'a LineGuide,
markers: &'a FileMarkers,
) -> (
FxHashSet<usize>,
FxHashMap<usize, Vec<(Point, Point, &'a Marker)>>,
Vec<(Point, Point, &'a Marker)>,
) {
let mut lines_set = FxHashSet::default();
let mut markers_by_line: FxHashMap<usize, Vec<(Point, Point, &Marker)>> = FxHashMap::default();
let mut multi_line_markers: Vec<(Point, Point, &Marker)> = Vec::new();
for marker in &markers.0 {
let start = guide.find(marker.position.start);
let end = guide.find(marker.position.end);
if let Some(row) = markers_by_line.get_mut(&start.line) {
row.push((start.clone(), end.clone(), &marker))
} else {
markers_by_line.insert(start.line, vec![(start.clone(), end.clone(), &marker)]);
}
if end.line != start.line {
multi_line_markers.push((start.clone(), end.clone(), &marker));
} else if marker.main {
// Just to make errors a little bit better
let start = start.line.saturating_sub(1);
let end = if start + 2 >= guide.len() {
guide.len() - 1
} else {
start + 2
};
for i in start..=end {
lines_set.insert(i);
}
}
if end.line - start.line <= 3 {
for i in start.line..=end.line {
lines_set.insert(i);
}
} else {
lines_set.insert(start.line);
lines_set.insert(end.line);
}
}
(lines_set, markers_by_line, multi_line_markers)
}

View File

@ -4,6 +4,7 @@ use crate::data::*;
use crate::report::code::{count_width, group_markers, LineGuide, Spaces};
use crate::report::code::{FileMarkers, Point};
use crate::RenderConfig;
use crate::report::group_marker_lines;
use fxhash::{FxHashMap, FxHashSet};
use pathdiff::diff_paths;
@ -127,56 +128,6 @@ fn mark_inlined<T: Write + Sized>(
Ok(())
}
fn group_marker_lines<'a>(
guide: &'a LineGuide,
markers: &'a FileMarkers,
) -> (
FxHashSet<usize>,
FxHashMap<usize, Vec<(Point, Point, &'a Marker)>>,
Vec<(Point, Point, &'a Marker)>,
) {
let mut lines_set = FxHashSet::default();
let mut markers_by_line: FxHashMap<usize, Vec<(Point, Point, &Marker)>> = FxHashMap::default();
let mut multi_line_markers: Vec<(Point, Point, &Marker)> = Vec::new();
for marker in &markers.0 {
let start = guide.find(marker.position.start);
let end = guide.find(marker.position.end);
if let Some(row) = markers_by_line.get_mut(&start.line) {
row.push((start.clone(), end.clone(), &marker))
} else {
markers_by_line.insert(start.line, vec![(start.clone(), end.clone(), &marker)]);
}
if end.line != start.line {
multi_line_markers.push((start.clone(), end.clone(), &marker));
} else if marker.main {
// Just to make errors a little bit better
let start = start.line.saturating_sub(1);
let end = if start + 2 >= guide.len() {
guide.len() - 1
} else {
start + 2
};
for i in start..=end {
lines_set.insert(i);
}
}
if end.line - start.line <= 3 {
for i in start.line..=end.line {
lines_set.insert(i);
}
} else {
lines_set.insert(start.line);
lines_set.insert(end.line);
}
}
(lines_set, markers_by_line, multi_line_markers)
}
fn paint_line<T>(data: T) -> Paint<T> {
Paint::new(data).fg(yansi::Color::Cyan).dimmed()
}
@ -213,7 +164,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 {
self.severity.render(fmt, cache, config)?;
Renderable::<Classic>::render(self.severity, fmt, cache, config)?;
fmt.write_str(&Paint::new(&self.title).bold().to_string())?;
fmt.write_char('\n')
}
@ -222,7 +173,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 {
match self {
Subtitle::Normal(color, phr) => {
Subtitle::Normal(color, phr) | Subtitle::Field(color, phr) => {
let bullet = color.colorize(config.chars.bullet);
writeln!(fmt, "{:>5} {} {}", "", bullet, Paint::new(phr))
}
@ -233,7 +184,7 @@ impl Renderable<Classic> for Subtitle {
Subtitle::Phrase(color, words) => {
let bullet = color.colorize(config.chars.bullet);
write!(fmt, "{:>5} {} ", "", bullet)?;
words.render(fmt, cache, config)?;
Renderable::<Classic>::render(words, fmt, cache, config)?;
writeln!(fmt)
}
Subtitle::LineBreak => {
@ -260,7 +211,7 @@ impl<'a> Renderable<Classic> for Subtitles<'a> {
writeln!(fmt)?;
}
self.0.render(fmt, cache, config)
Renderable::<Classic>::render(self.0, fmt, cache, config)
}
}
@ -456,7 +407,7 @@ impl<'a> Renderable<Classic> for Markers<'a> {
markers,
};
block.render(fmt, cache, config)?;
Renderable::<Classic>::render(&block, fmt, cache, config)?;
}
if !is_empty {
@ -487,18 +438,11 @@ impl Renderable<Classic> for DiagnosticFrame {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
write!(fmt, " ")?;
self.header().render(fmt, cache, config)?;
self.subtitles().render(fmt, cache, config)?;
self.markers().render(fmt, cache, config)?;
self.hints().render(fmt, cache, config)?;
Renderable::<Classic>::render(&self.header(), fmt, cache, config)?;
Renderable::<Classic>::render(&self.subtitles(), fmt, cache, config)?;
Renderable::<Classic>::render(&self.markers(), fmt, cache, config)?;
Renderable::<Classic>::render(&self.hints(), fmt, cache, config)?;
Ok(())
}
}
impl<T> Renderable<T> for Box<dyn Diagnostic> {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
self.to_diagnostic_frame().render(fmt, cache, config)
}
}
}

View File

@ -0,0 +1,180 @@
use std::{fmt::Write, path::PathBuf};
use pathdiff::diff_paths;
use crate::data::*;
use crate::{report::*, RenderConfig};
use super::{CodeBlock, Compact, Renderable, Res};
fn colorize_code<T: Write + Sized>(
markers: &mut [&(Point, Point, &Marker)],
code_line: &str,
fmt: &mut T,
) -> std::fmt::Result {
markers.sort_by(|x, y| x.0.column.cmp(&y.0.column));
let mut start = 0;
for marker in markers {
if start < marker.0.column {
write!(fmt, "{}", &code_line[start..marker.0.column])?;
start = marker.0.column;
}
let end = if marker.0.line == marker.1.line {
marker.1.column
} else {
code_line.len()
};
if start < end {
write!(fmt, "{{{{{}}}}}", &code_line[start..end])?;
start = end;
}
}
if start < code_line.len() {
write!(fmt, "{}}}}}", &code_line[start..code_line.len()])?;
}
writeln!(fmt)?;
Ok(())
}
impl<'a> Renderable<Compact> for Word {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
match self {
Word::Normal(str) => write!(fmt, "{} ", str),
Word::Dimmed(str) => write!(fmt, "{} ", str),
Word::White(str) => write!(fmt, "{} ", str),
Word::Painted(_, str) => write!(fmt, "{} ", str),
}
}
}
impl Renderable<Compact> for Subtitle {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
match self {
Subtitle::Field(_, phr) => writeln!(fmt, "{}", phr.to_lowercase()),
Subtitle::Normal(_, phr) => writeln!(fmt, "- {}", phr),
Subtitle::Bold(_, phr) => writeln!(fmt, "- {}", phr),
Subtitle::Phrase(_, words) => {
write!(fmt, "- ")?;
Renderable::<Compact>::render(words, fmt, cache, config)?;
writeln!(fmt)
}
Subtitle::LineBreak => Ok(()),
}
}
}
impl<'a> Renderable<Compact> for Subtitles<'a> {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
if !self.0.is_empty() {
writeln!(fmt)?;
}
Renderable::<Compact>::render(self.0, fmt, cache, config)
}
}
impl Renderable<Compact> for Severity {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
use Severity::*;
let painted = match self {
Error => "error:",
Warning => "warn:",
Info => "info:",
};
write!(fmt, " {} ", painted)
}
}
impl<'a> Renderable<Compact> for Header<'a> {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
fmt.write_str(&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 {
writeln!(fmt, "location")?;
let guide = LineGuide::get(self.code);
let (lines_set, mut by_line, _) = group_marker_lines(&guide, self.markers);
let code_lines: Vec<&'a str> = self.code.lines().collect();
let mut lines: Vec<usize> = lines_set
.into_iter()
.filter(|x| *x < code_lines.len())
.collect();
lines.sort();
for line in lines {
let mut empty_vec = Vec::new();
let row = by_line.get_mut(&line).unwrap_or(&mut empty_vec);
let mut inline_markers: Vec<&(Point, Point, &Marker)> =
row.iter().filter(|x| x.0.line == x.1.line).collect();
if !inline_markers.is_empty() {
colorize_code(&mut inline_markers, code_lines[line], fmt)?;
} else {
writeln!(fmt, "{}", code_lines[line])?;
}
}
Ok(())
}
}
impl<'a> Renderable<Compact> for Markers<'a> {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, cache: &C, config: &RenderConfig) -> Res {
let groups = group_markers(&self.0);
let current = PathBuf::from(".").canonicalize().unwrap();
for (ctx, markers) in groups.iter() {
let (file, code) = cache.fetch(*ctx).unwrap();
let path = diff_paths(&file.clone(), current.clone()).unwrap_or(file);
let block = CodeBlock {
code,
path: &path,
markers,
};
Renderable::<Compact>::render(&block, fmt, cache, config)?;
}
Ok(())
}
}
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 {
Renderable::<Compact>::render(&self.header(), fmt, cache, config)?;
Renderable::<Compact>::render(&self.subtitles(), fmt, cache, config)?;
Renderable::<Compact>::render(&self.markers(), fmt, cache, config)?;
Ok(())
}
}
impl Renderable<Compact> for Log {
fn render<U: Write, C: FileCache>(&self, fmt: &mut U, _: &C, _: &RenderConfig) -> Res {
match self {
Log::Compiled(_) => writeln!(fmt, "compiled"),
Log::Checked(_) => writeln!(fmt, "checked"),
_ => Ok(()),
}
}
}

View File

@ -1,10 +1,12 @@
use std::{fmt::Write, path::Path};
use crate::{data::FileCache, RenderConfig};
use refl::Id;
use crate::{data::{FileCache, Diagnostic, DiagnosticFrame, Log}, RenderConfig};
use super::code::FileMarkers;
pub mod classic;
pub mod compact;
// Just a type synonym to make it easier to read.
pub type Res = std::fmt::Result;
@ -22,6 +24,13 @@ pub enum Classic {}
/// LLM.
pub enum Compact {}
/// The enum of all of the modes so we can choose
#[derive(Debug, Clone, Copy)]
pub enum Mode {
Classic,
Compact,
}
// Utilities
/// Utility for easier renders
@ -45,3 +54,21 @@ impl<'a, T, E> Renderable<T> for Vec<E> where E : Renderable<T> {
Ok(())
}
}
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 {
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 {
match config.mode {
Mode::Classic => Renderable::<Classic>::render(self, fmt, cache, config),
Mode::Compact => Renderable::<Compact>::render(self, fmt, cache, config),
}
}
}
impl Report for Box<dyn Diagnostic> {}
impl Report for Log {}

View File

@ -1,4 +1,4 @@
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity};
use kind_report::{data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity}, RenderConfig};
use kind_span::Range;
pub enum KdlDiagnostic {
@ -20,7 +20,7 @@ impl Diagnostic for KdlDiagnostic {
}
}
fn to_diagnostic_frame(&self) -> kind_report::data::DiagnosticFrame {
fn to_diagnostic_frame(&self, _: &RenderConfig) -> kind_report::data::DiagnosticFrame {
match self {
KdlDiagnostic::InvalidVarName(s, range) => DiagnosticFrame {
code: 600,

View File

@ -1,6 +1,6 @@
INFO Inspection.
INFO Inspection
* Expected: U60
* Hole: U60
/--[suite/checker/Inspection.kind2:3:3]

View File

@ -1,14 +1,14 @@
INFO Inspection.
INFO Inspection
* Expected: U60
* Hole: U60
* Context:
* awoo : Type
* awoo = U60
* uuuhuuul : (List awoo)
* uuuhuuul = (List.nil awoo)
* ooooooo : (List U60)
* ooooooo = uuuhuuul
* Context
* awoo : Type
* awoo = U60
* uuuhuuul : (List awoo)
* uuuhuuul = (List.nil awoo)
* ooooooo : (List U60)
* ooooooo = uuuhuuul
/--[suite/checker/Subst.kind2:11:5]
|

View File

@ -3,12 +3,12 @@
* Got : ((x_1 : Type) -> (x_2 : Type) -> Type)
* Expected : ((x_1 : t) -> (x_2 : t) -> t)
* Context:
* t : Type
* t_ : Type
* t_ = t
* magma : (Algebra.Magma Type)
* assoc : ((a : _) -> (b : _) -> (c : _) -> (Equal _ (((Algebra.Magma.concat _ magma) (((Algebra.Magma.concat _ magma) a) b)) c) (((Algebra.Magma.concat _ magma) a) (((Algebra.Magma.concat _ magma) b) c))))
* Context
* t : Type
* t_ : Type
* t_ = t
* magma : (Algebra.Magma Type)
* assoc : ((a : _) -> (b : _) -> (c : _) -> (Equal _ (((Algebra.Magma.concat _ magma) (((Algebra.Magma.concat _ magma) a) b)) c) (((Algebra.Magma.concat _ magma) a) (((Algebra.Magma.concat _ magma) b) c))))
/--[suite/checker/fail/MismatchOne.kind2:32:69]
|

View File

@ -3,8 +3,8 @@
* Got : Type
* Expected : U60
* Context:
* a : U60
* Context
* a : U60
/--[suite/checker/fail/MismatchTwo.kind2:2:10]
|

View File

@ -1,9 +1,9 @@
INFO Inspection.
INFO Inspection
* Expected: (Assert (Nat.count_layers n 1))
* Hole: (Assert (Nat.count_layers n 1))
* Context:
* n : Nat
* Context
* n : Nat
/--[suite/issues/checker/HvmReducesTooMuch.kind2:14:29]
|

View File

@ -1,11 +1,11 @@
INFO Inspection.
INFO Inspection
* Expected: U60
* Hole: U60
* Context:
* n : (Pair U60 U60)
* n.fst : U60
* n.snd : U60
* Context
* n : (Pair U60 U60)
* n.fst : U60
* n.snd : U60
/--[suite/issues/checker/ISSUE-457.kind2:10:16]
|
@ -16,14 +16,14 @@
11 | }
INFO Inspection.
INFO Inspection
* Expected: U60
* Hole: U60
* Context:
* n : (Pair U60 U60)
* n.fst : U60
* n.snd : U60
* Context
* n : (Pair U60 U60)
* n.fst : U60
* n.snd : U60
/--[suite/issues/checker/ISSUE-457.kind2:17:5]
|
@ -34,14 +34,14 @@
18 |
INFO Inspection.
INFO Inspection
* Expected: U60
* Hole: U60
* Context:
* n : (Pair U60 U60)
* fst : U60
* snd : U60
* Context
* n : (Pair U60 U60)
* fst : U60
* snd : U60
/--[suite/issues/checker/ISSUE-457.kind2:22:5]
|

View File

@ -1,14 +1,14 @@
INFO Inspection.
INFO Inspection
* Expected: U60
* Hole: U60
* Context:
* awoo : Type
* awoo = U60
* uuuhuuul : (List awoo)
* uuuhuuul = (List.nil awoo)
* ooooooo : (List U60)
* ooooooo = uuuhuuul
* Context
* awoo : Type
* awoo = U60
* uuuhuuul : (List awoo)
* uuuhuuul = (List.nil awoo)
* ooooooo : (List U60)
* ooooooo = uuuhuuul
/--[suite/issues/checker/ISSUE-461.kind2:11:5]
|

View File

@ -3,10 +3,10 @@
* Got : (Run n)
* Expected : U60
* Context:
* t1 : Type
* n : Nat
* f : (Run n)
* Context
* t1 : Type
* n : Nat
* f : (Run n)
/--[suite/issues/checker/TestWith.kind2:14:22]
|

View File

@ -1,6 +1,6 @@
INFO Inspection.
INFO Inspection
* Expected: (Equal _ 2n 5n)
* Hole: (Equal _ 2n 5n)
/--[suite/issues/checker/U60ToNatDoesNotReduce.kind2:30:17]

View File

@ -40,7 +40,7 @@ fn test_kind2(path: &Path, run: fn(&PathBuf, &mut Session) -> Option<String>) ->
let res = run(&PathBuf::from(path), &mut session);
let diagnostics = tx.try_iter().collect::<Vec<Box<dyn Diagnostic>>>();
let render = RenderConfig::ascii(2);
let render = RenderConfig::ascii(2, false);
kind_report::check_if_colors_are_supported(true);