diff --git a/src/elements/blockquote.rs b/src/elements/blockquote.rs index fb5cb4c..364bfb3 100644 --- a/src/elements/blockquote.rs +++ b/src/elements/blockquote.rs @@ -4,9 +4,6 @@ use std::collections::HashMap; use std::ops::Range; use std::rc::Rc; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use blockquote_style::AuthorPos::After; use blockquote_style::AuthorPos::Before; use blockquote_style::BlockquoteStyle; @@ -36,6 +33,8 @@ use crate::parser::style::StyleHolder; use crate::parser::util::escape_text; use crate::parser::util::Property; use crate::parser::util::PropertyParser; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; #[derive(Debug)] pub struct Blockquote { @@ -254,7 +253,7 @@ impl Rule for BlockquoteRule { document: &'a (dyn Document<'a> + 'a), cursor: Cursor, _match_data: Box, - ) -> (Cursor, Vec, Range)>>) { + ) -> (Cursor, Vec) { let mut reports = vec![]; let content = cursor.source.content(); @@ -273,19 +272,8 @@ impl Rule for BlockquoteRule { if let Some(properties) = captures.get(1) { match self.parse_properties(properties) { Err(err) => { - reports.push( - Report::build( - ReportKind::Warning, - cursor.source.clone(), - properties.start(), - ) - .with_message("Invalid Blockquote Properties") - .with_label( - Label::new((cursor.source.clone(), properties.range())) - .with_message(err) - .with_color(state.parser.colors().warning), - ) - .finish(), + report_err!(&mut reports, cursor.source.clone(), "Invalid Blockquote Properties".into(), + span(properties.range(), err) ); return (end_cursor, reports); } @@ -342,15 +330,8 @@ impl Rule for BlockquoteRule { } else if elem.downcast_ref::
().is_some() { parsed_content.push(elem); } else { - reports.push( - Report::build(ReportKind::Error, token.source(), token.range.start) - .with_message("Unable to Parse Blockquote Entry") - .with_label( - Label::new((token.source(), token.range.clone())) - .with_message("Blockquotes may only contain paragraphs and other blockquotes") - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!(&mut reports, token.source(), "Unable to Parse Blockquote Entry".into(), + span(token.range.clone(), "Blockquotes may only contain paragraphs and other blockquotes".into()) ); return (end_cursor, reports); } diff --git a/src/elements/customstyle.rs b/src/elements/customstyle.rs index d010904..aefaf84 100644 --- a/src/elements/customstyle.rs +++ b/src/elements/customstyle.rs @@ -9,9 +9,6 @@ use std::rc::Rc; use std::sync::Arc; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Error::BadArgument; use mlua::Function; use mlua::Lua; @@ -29,6 +26,8 @@ use crate::parser::source::Source; use crate::parser::source::Token; use crate::parser::state::RuleState; use crate::parser::state::Scope; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; use super::paragraph::Paragraph; @@ -50,7 +49,7 @@ impl CustomStyle for LuaCustomStyle { location: Token, state: &ParserState, document: &'a dyn Document<'a>, - ) -> Vec, Range)>> { + ) -> Vec { let kernel: Ref<'_, Kernel> = Ref::map(state.shared.kernels.borrow(), |b| b.get("main").unwrap()); //let kernel = RefMut::map(parser_state.shared.kernels.borrow(), |ker| ker.get("main").unwrap()); @@ -64,19 +63,12 @@ impl CustomStyle for LuaCustomStyle { kernel.run_with_context(ctx, |lua| { let chunk = lua.load(self.start.as_str()); if let Err(err) = chunk.eval::<()>() { - reports.push( - Report::build(ReportKind::Error, location.source(), location.start()) - .with_message("Lua execution failed") - .with_label( - Label::new((location.source(), location.range.clone())) - .with_message(err.to_string()) - .with_color(state.parser.colors().error), - ) - .with_note(format!( + report_err!(&mut reports, location.source(), "Lua execution failed".into(), + span(location.range.clone(), err.to_string()), + note(format!( "When trying to start custom style {}", self.name().fg(state.parser.colors().info) )) - .finish(), ); } }); @@ -89,7 +81,7 @@ impl CustomStyle for LuaCustomStyle { location: Token, state: &ParserState, document: &'a dyn Document<'a>, - ) -> Vec, Range)>> { + ) -> Vec { let kernel: Ref<'_, Kernel> = Ref::map(state.shared.kernels.borrow(), |b| b.get("main").unwrap()); let ctx = KernelContext { @@ -102,19 +94,12 @@ impl CustomStyle for LuaCustomStyle { kernel.run_with_context(ctx, |lua| { let chunk = lua.load(self.end.as_str()); if let Err(err) = chunk.eval::<()>() { - reports.push( - Report::build(ReportKind::Error, location.source(), location.start()) - .with_message("Lua execution failed") - .with_label( - Label::new((location.source(), location.range.clone())) - .with_message(err.to_string()) - .with_color(state.parser.colors().error), - ) - .with_note(format!( + report_err!(&mut reports, location.source(), "Lua execution failed".into(), + span(location.range.clone(), err.to_string()), + note(format!( "When trying to end custom style {}", self.name().fg(state.parser.colors().info) - )) - .finish(), + )) ); } }); @@ -130,11 +115,11 @@ struct CustomStyleState { impl RuleState for CustomStyleState { fn scope(&self) -> Scope { Scope::PARAGRAPH } - fn on_remove<'a>( + fn on_remove( &self, state: &ParserState, document: &dyn Document, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; self.toggled.iter().for_each(|(style, token)| { @@ -150,26 +135,13 @@ impl RuleState for CustomStyleState { }) .unwrap(); - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Unterminated Custom Style") - .with_label( - Label::new((token.source(), token.range.clone())) - .with_order(1) - .with_message(format!( + report_err!(&mut reports, token.source(), "Unterminated Custom Style".into(), + span(token.range.clone(), format!( "Style {} starts here", style.fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), - ) - .with_label( - Label::new(paragraph_end) - .with_order(1) - .with_message("Paragraph ends here".to_string()) - .with_color(state.parser.colors().error), - ) - .with_note("Styles cannot span multiple documents (i.e @import)") - .finish(), + )), + span(paragraph_end.1, "Paragraph ends here".into()), + note("Styles cannot span multiple documents (i.e @import)".into()) ); }); @@ -248,7 +220,7 @@ impl Rule for CustomStyleRule { document: &'a dyn Document<'a>, cursor: Cursor, match_data: Box, - ) -> (Cursor, Vec, Range)>>) { + ) -> (Cursor, Vec) { let (style, end) = match_data .downcast_ref::<(Rc, bool)>() .unwrap(); @@ -299,22 +271,16 @@ impl Rule for CustomStyleRule { let token = Token::new(cursor.pos..cursor.pos + s_end.len(), cursor.source.clone()); if style_state.toggled.get(style.name()).is_none() { - return ( - cursor.at(cursor.pos + s_end.len()), - vec![ - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid End of Style") - .with_label( - Label::new((token.source(), token.range.clone())) - .with_order(1) - .with_message(format!( - "Cannot end style {} here, is it not started anywhere", + let mut reports = vec![]; + report_err!(&mut reports, token.source(), "Invalid End of Style".into(), + span(token.range.clone(), format!( + "Cannot end style {} here, it does not started anywhere", style.name().fg(state.parser.colors().info) )) - .with_color(state.parser.colors().error), - ) - .finish(), - ], + ); + return ( + cursor.at(cursor.pos + s_end.len()), + reports ); } @@ -327,33 +293,20 @@ impl Rule for CustomStyleRule { cursor.source.clone(), ); if let Some(start_token) = style_state.toggled.get(style.name()) { + let mut reports = vec![]; + report_err!(&mut reports, token.source(), "Invalid Start of Style".into(), + span(token.range.clone(), format!( + "When trying to start custom style {}", + self.name().fg(state.parser.colors().info) + )), + span(start_token.range.clone(), format!( + "Style {} previously starts here", + self.name().fg(state.parser.colors().info) + )), + ); return ( cursor.at(cursor.pos + s_end.len()), - vec![Report::build( - ReportKind::Error, - start_token.source(), - start_token.start(), - ) - .with_message("Invalid Start of Style") - .with_label( - Label::new((token.source(), token.range.clone())) - .with_order(1) - .with_message(format!( - "Style cannot {} starts here", - style.name().fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), - ) - .with_label( - Label::new((start_token.source(), start_token.range.clone())) - .with_order(2) - .with_message(format!( - "Style {} starts previously here", - style.name().fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), - ) - .finish()], + reports ); } diff --git a/src/elements/elemstyle.rs b/src/elements/elemstyle.rs index c5e7b40..b800824 100644 --- a/src/elements/elemstyle.rs +++ b/src/elements/elemstyle.rs @@ -6,9 +6,6 @@ use std::rc::Rc; use std::sync::Arc; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Error::BadArgument; use mlua::Function; use mlua::Lua; @@ -18,9 +15,10 @@ use regex::Regex; use crate::document::document::Document; use crate::lua::kernel::CTX; use crate::parser::parser::ParserState; +use crate::parser::reports::macros::*; +use crate::parser::reports::*; use crate::parser::rule::Rule; use crate::parser::source::Cursor; -use crate::parser::source::Source; #[auto_registry::auto_registry(registry = "rules", path = "crate::elements::elemstyle")] pub struct ElemStyleRule { @@ -80,7 +78,7 @@ impl Rule for ElemStyleRule { _document: &'a (dyn Document<'a> + 'a), cursor: Cursor, _match_data: Box, - ) -> (Cursor, Vec, Range)>>) { + ) -> (Cursor, Vec) { let mut reports = vec![]; let matches = self .start_re @@ -93,33 +91,28 @@ impl Rule for ElemStyleRule { // Check if empty if trimmed.is_empty() { - reports.push( - Report::build(ReportKind::Error, cursor.source.clone(), key.start()) - .with_message("Empty Style Key") - .with_label( - Label::new((cursor.source.clone(), key.range())) - .with_message("Expected a non-empty style key".to_string()) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + cursor.source.clone(), + "Empty Style Key".into(), + span(key.range(), "Expected a non-empty style key".into()), ); return (cursor, reports); } // Check if key exists if !state.shared.styles.borrow().is_registered(trimmed) { - reports.push( - Report::build(ReportKind::Error, cursor.source.clone(), key.start()) - .with_message("Unknown Style Key") - .with_label( - Label::new((cursor.source.clone(), key.range())) - .with_message(format!( - "Could not find a style with key: {}", - trimmed.fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + cursor.source.clone(), + "Unknown Style Key".into(), + span( + key.range(), + format!( + "Could not find a style with key: {}", + trimmed.fg(state.parser.colors().info) ) - .finish(), + ), ); return (cursor, reports); @@ -135,17 +128,14 @@ impl Rule for ElemStyleRule { &cursor.source.clone().content().as_str()[cursor.pos..], ) { None => { - reports.push( - Report::build(ReportKind::Error, cursor.source.clone(), cursor.pos) - .with_message("Invalid Style Value") - .with_label( - Label::new((cursor.source.clone(), matches.get(0).unwrap().range())) - .with_message( - "Unable to parse json string after style key".to_string(), - ) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + cursor.source.clone(), + "Invalid Style Value".into(), + span( + matches.get(0).unwrap().range(), + "Unable to parse json string after style key".into() + ) ); return (cursor, reports); } @@ -155,22 +145,18 @@ impl Rule for ElemStyleRule { // Attempt to deserialize match style.from_json(json) { Err(err) => { - reports.push( - Report::build(ReportKind::Error, cursor.source.clone(), cursor.pos) - .with_message("Invalid Style Value") - .with_label( - Label::new(( - cursor.source.clone(), - cursor.pos..cursor.pos + json.len(), - )) - .with_message(format!( + report_err!( + &mut reports, + cursor.source.clone(), + "Invalid Style Value".into(), + span( + cursor.pos..cursor.pos + json.len(), + format!( "Failed to serialize `{}` into style with key `{}`: {err}", json.fg(state.parser.colors().highlight), style.key().fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), ) - .finish(), + ) ); return (cursor, reports); } diff --git a/src/elements/layout.rs b/src/elements/layout.rs index daa7e12..d4cc825 100644 --- a/src/elements/layout.rs +++ b/src/elements/layout.rs @@ -17,9 +17,6 @@ use crate::parser::state::RuleState; use crate::parser::state::Scope; use crate::parser::util::escape_text; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Error::BadArgument; use mlua::Function; use mlua::Lua; @@ -34,6 +31,8 @@ use std::ops::Range; use std::rc::Rc; use std::str::FromStr; use std::sync::Arc; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum LayoutToken { @@ -253,11 +252,11 @@ struct LayoutState { impl RuleState for LayoutState { fn scope(&self) -> Scope { Scope::DOCUMENT } - fn on_remove<'a>( + fn on_remove( &self, state: &ParserState, document: &dyn Document, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; let doc_borrow = document.content().borrow(); @@ -265,25 +264,23 @@ impl RuleState for LayoutState { for (tokens, layout_type) in &self.stack { let start = tokens.first().unwrap(); - reports.push( - Report::build(ReportKind::Error, start.source(), start.start()) - .with_message("Unterminated Layout") - .with_label( - Label::new((start.source(), start.range.start + 1..start.range.end)) - .with_order(1) - .with_message(format!( - "Layout {} stars here", - layout_type.name().fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + start.source(), + "Unterminated Layout".into(), + span( + start.source(), + start.range.start+1..start.range.end, + format!( + "Layout {} stars here", + layout_type.name().fg(state.parser.colors().info) ) - .with_label( - Label::new((at.source(), at.range.clone())) - .with_order(2) - .with_message("Document ends here".to_string()) - .with_color(state.parser.colors().error), - ) - .finish(), + ), + span( + at.source(), + at.range.clone(), + "Document ends here".into() + ) ); } @@ -340,24 +337,26 @@ impl LayoutRule { } pub fn parse_properties<'a>( - colors: &ReportColors, + mut reports: &mut Vec, token: &Token, layout_type: Rc, properties: Option, - ) -> Result>, Report<'a, (Rc, Range)>> { + ) -> Option> { match properties { None => match layout_type.parse_properties("") { - Ok(props) => Ok(props), - Err(err) => Err( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Unable to parse layout properties") - .with_label( - Label::new((token.source(), token.range.clone())) - .with_message(err) - .with_color(colors.error), + Ok(props) => props, + Err(err) => { + report_err!( + &mut reports, + token.source(), + "Invalid Layout Properties".into(), + span( + token.range.clone(), + format!("Layout is missing required property: {eee}") ) - .finish(), - ), + ); + None + } }, Some(props) => { let trimmed = props.as_str().trim_start().trim_end(); diff --git a/src/elements/link.rs b/src/elements/link.rs index 74c6d1e..3fdacaa 100644 --- a/src/elements/link.rs +++ b/src/elements/link.rs @@ -14,9 +14,6 @@ use crate::parser::source::Token; use crate::parser::source::VirtualSource; use crate::parser::util; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Error::BadArgument; use mlua::Function; use mlua::Lua; @@ -25,6 +22,8 @@ use regex::Regex; use std::ops::Range; use std::rc::Rc; use std::sync::Arc; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; #[derive(Debug)] pub struct Link { @@ -109,39 +108,37 @@ impl RegexRule for LinkRule { document: &'a (dyn Document<'a> + 'a), token: Token, matches: Captures, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; let link_display = match matches.get(1) { Some(display) => { if display.as_str().is_empty() { - reports.push( - Report::build(ReportKind::Error, token.source(), display.start()) - .with_message("Empty link name") - .with_label( - Label::new((token.source().clone(), display.range())) - .with_message("Link name is empty") - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Empty Link Display".into(), + span( + display.range(), + "Link display is empty".into() + ) ); return reports; } let display_source = util::escape_source(token.source(), display.range(), "Link Display".into(), '\\', "]("); if display_source.content().is_empty() { - reports.push( - Report::build(ReportKind::Error, token.source(), display.start()) - .with_message("Empty link name") - .with_label( - Label::new((token.source(), display.range())) - .with_message(format!( - "Link name is empty. Once processed, `{}` yields `{}`", - display.as_str().fg(state.parser.colors().highlight), - display_source.fg(state.parser.colors().highlight), - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Empty Link Display".into(), + span( + display.range(), + format!( + "Link name is empty. Once processed, `{}` yields `{}`", + display.as_str().fg(state.parser.colors().highlight), + display_source.fg(state.parser.colors().highlight), ) - .finish(), + ) ); return reports; } @@ -156,15 +153,14 @@ impl RegexRule for LinkRule { } match util::parse_paragraph(state, display_source, document) { Err(err) => { - reports.push( - Report::build(ReportKind::Error, token.source(), display.start()) - .with_message("Failed to parse link display") - .with_label( - Label::new((token.source(), display.range())) - .with_message(err.to_string()) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Link Display".into(), + span( + display.range(), + format!("Failed to parse link display:\n{err}") + ) ); return reports; } @@ -177,34 +173,32 @@ impl RegexRule for LinkRule { let link_url = match matches.get(2) { Some(url) => { if url.as_str().is_empty() { - reports.push( - Report::build(ReportKind::Error, token.source(), url.start()) - .with_message("Empty link url") - .with_label( - Label::new((token.source(), url.range())) - .with_message("Link url is empty") - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Empty Link URL".into(), + span( + url.range(), + "Link url is empty".into() + ) ); return reports; } let text_content = util::process_text(document, url.as_str()); if text_content.is_empty() { - reports.push( - Report::build(ReportKind::Error, token.source(), url.start()) - .with_message("Empty link url") - .with_label( - Label::new((token.source(), url.range())) - .with_message(format!( - "Link url is empty. Once processed, `{}` yields `{}`", - url.as_str().fg(state.parser.colors().highlight), - text_content.as_str().fg(state.parser.colors().highlight), - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Empty Link URL".into(), + span( + url.range(), + format!( + "Link url is empty. Once processed, `{}` yields `{}`", + url.as_str().fg(state.parser.colors().highlight), + text_content.as_str().fg(state.parser.colors().highlight), ) - .finish(), + ) ); return reports; } diff --git a/src/elements/list.rs b/src/elements/list.rs index 538d3bd..045a591 100644 --- a/src/elements/list.rs +++ b/src/elements/list.rs @@ -14,9 +14,9 @@ use crate::document::element::Element; use crate::lsp::semantic::Semantics; use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; +use crate::parser::reports::Report; use crate::parser::rule::Rule; use crate::parser::source::Cursor; -use crate::parser::source::Source; use crate::parser::source::Token; use crate::parser::source::VirtualSource; use crate::parser::util; @@ -24,9 +24,8 @@ use crate::parser::util::escape_text; use crate::parser::util::Property; use crate::parser::util::PropertyMapError; use crate::parser::util::PropertyParser; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; use regex::Match; use regex::Regex; @@ -293,7 +292,7 @@ impl Rule for ListRule { document: &'a dyn Document<'a>, cursor: Cursor, _match_data: Box, - ) -> (Cursor, Vec, Range)>>) { + ) -> (Cursor, Vec) { let mut reports = vec![]; let content = cursor.source.content(); @@ -312,19 +311,8 @@ impl Rule for ListRule { if let Some(properties) = captures.get(2) { match self.parse_properties(properties) { Err(err) => { - reports.push( - Report::build( - ReportKind::Warning, - cursor.source.clone(), - properties.start(), - ) - .with_message("Invalid List Entry Properties") - .with_label( - Label::new((cursor.source.clone(), properties.range())) - .with_message(err) - .with_color(state.parser.colors().warning), - ) - .finish(), + report_err!(&mut reports, cursor.source.clone(), "Invalid List Entry Properties".into(), + span(properties.range(), err) ); return (cursor.at(captures.get(0).unwrap().end()), reports); } @@ -391,15 +379,8 @@ impl Rule for ListRule { )); let parsed_content = match util::parse_paragraph(state, entry_src, document) { Err(err) => { - reports.push( - Report::build(ReportKind::Warning, token.source(), token.range.start) - .with_message("Unable to Parse List Entry") - .with_label( - Label::new((token.source(), token.range.clone())) - .with_message(err) - .with_color(state.parser.colors().warning), - ) - .finish(), + report_warn!(&mut reports, token.source(), "Unable to parse List Entry".into(), + span(token.range.clone(), err.into()) ); // Return an empty paragraph vec![] diff --git a/src/elements/media.rs b/src/elements/media.rs index d2cd47d..fdfab56 100644 --- a/src/elements/media.rs +++ b/src/elements/media.rs @@ -4,9 +4,6 @@ use std::rc::Rc; use std::str::FromStr; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use regex::Captures; use regex::Match; use regex::Regex; @@ -34,6 +31,8 @@ use crate::parser::util::Property; use crate::parser::util::PropertyMap; use crate::parser::util::PropertyMapError; use crate::parser::util::PropertyParser; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; use super::paragraph::Paragraph; use super::reference::InternalReference; @@ -286,39 +285,43 @@ impl MediaRule { fn parse_properties( &self, - colors: &ReportColors, + mut reports: &mut Vec, token: &Token, m: &Option, - ) -> Result, Range)>> { + ) -> Option { match m { None => match self.properties.default() { - Ok(properties) => Ok(properties), - Err(e) => Err( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Media Properties") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!("Media is missing required property: {e}")) - .with_color(colors.error), + Ok(properties) => Some(properties), + Err(e) => { + report_err!( + &mut reports, + token.source(), + "Invalid Media Properties".into(), + span( + token.range.clone(), + format!("Media is missing required property: {e}") ) - .finish(), - ), + ); + None + } }, Some(props) => { let processed = util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { - Err(e) => Err( - Report::build(ReportKind::Error, token.source(), props.start()) - .with_message("Invalid Media Properties") - .with_label( - Label::new((token.source().clone(), props.range())) - .with_message(e) - .with_color(colors.error), + Err(e) => { + report_err!( + &mut reports, + token.source(), + "Invalid Media Properties".into(), + span( + props.range(), + e ) - .finish(), - ), - Ok(properties) => Ok(properties), + ); + None + }, + Ok(properties) => Some(properties), } } } @@ -357,7 +360,7 @@ impl RegexRule for MediaRule { document: &'a (dyn Document<'a> + 'a), token: Token, matches: Captures, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; let refname = match ( @@ -366,13 +369,14 @@ impl RegexRule for MediaRule { ) { (_, Ok(refname)) => refname.to_string(), (m, Err(err)) => { - reports.push( - Report::build(ReportKind::Error, token.source(), m.start()) - .with_message("Invalid Media Refname") - .with_label( - Label::new((token.source().clone(), m.range())).with_message(err), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Media Refname".into(), + span( + m.range(), + err + ) ); return reports; } @@ -384,26 +388,24 @@ impl RegexRule for MediaRule { ) { (_, Ok(uri)) => util::escape_text('\\', ")", uri), (m, Err(err)) => { - reports.push( - Report::build(ReportKind::Error, token.source(), m.start()) - .with_message("Invalid Media URI") - .with_label( - Label::new((token.source().clone(), m.range())).with_message(err), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Media URI".into(), + span( + m.range(), + err + ) ); return reports; } }; // Properties - let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(3)) + let properties = match self.parse_properties(&mut reports, &token, &matches.get(3)) { - Ok(pm) => pm, - Err(report) => { - reports.push(report); - return reports; - } + Some(pm) => pm, + None => return reports, }; let media_type = @@ -415,36 +417,31 @@ impl RegexRule for MediaRule { Ok((_prop, kind)) => kind, Err(e) => match e { PropertyMapError::ParseError((prop, err)) => { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Media Property") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!( - "Property `type: {}` cannot be converted: {}", - prop.fg(state.parser.colors().info), - err.fg(state.parser.colors().error) - )) - .with_color(state.parser.colors().warning), + report_err!( + &mut reports, + token.source(), + "Invalid Media Property".into(), + span( + token.start()+1..token.end(), + format!( + "Property `type: {}` cannot be converted: {}", + prop.fg(state.parser.colors().info), + err.fg(state.parser.colors().error) ) - .finish(), + ) ); return reports; } PropertyMapError::NotFoundError(err) => { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Media Property") - .with_label( - Label::new(( - token.source().clone(), - token.start() + 1..token.end(), - )) - .with_message(format!("{err}. Required because mediatype could not be detected")) - .with_color(state.parser.colors().error), - ) - .finish(), - ); + report_err!( + &mut reports, + token.source(), + "Invalid Media Property".into(), + span( + token.start()+1..token.end(), + format!("{err}. Required because mediatype could not be detected") + ) + ); return reports; } }, @@ -478,17 +475,16 @@ impl RegexRule for MediaRule { match parse_paragraph(state, source, document) { Ok(paragraph) => Some(*paragraph), Err(err) => { - reports.push( - Report::build(ReportKind::Error, token.source(), content.start()) - .with_message("Invalid Media Description") - .with_label( - Label::new((token.source().clone(), content.range())) - .with_message(format!( - "Could not parse description: {err}" - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Invalid Media Description".into(), + span( + content.range(), + format!( + "Could not parse description: {err}" ) - .finish(), + ) ); return reports; } @@ -522,15 +518,15 @@ impl RegexRule for MediaRule { caption, description, })) { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Media") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(err) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Media".into(), + span( + token.range.clone(), + err + + ) ); } diff --git a/src/elements/raw.rs b/src/elements/raw.rs index 23bc6b6..cfa190e 100644 --- a/src/elements/raw.rs +++ b/src/elements/raw.rs @@ -6,25 +6,21 @@ use crate::lsp::semantic::Semantics; use crate::lua::kernel::CTX; use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; use crate::parser::rule::RegexRule; -use crate::parser::source::Source; use crate::parser::source::Token; use crate::parser::util::Property; use crate::parser::util::PropertyMapError; use crate::parser::util::PropertyParser; use crate::parser::util::{self}; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Error::BadArgument; use mlua::Function; use mlua::Lua; use regex::Captures; use regex::Regex; use std::collections::HashMap; -use std::ops::Range; -use std::rc::Rc; use std::str::FromStr; use std::sync::Arc; @@ -94,25 +90,24 @@ impl RegexRule for RawRule { document: &dyn Document, token: Token, matches: Captures, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; let raw_content = match matches.get(2) { // Unterminated None => { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Unterminated Raw Code") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!( - "Missing terminating `{}` after first `{}`", - "?}".fg(state.parser.colors().info), - "{?".fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Unterminated Raw Code".into(), + span( + token.range.clone(), + format!( + "Missing terminating `{}` after first `{}`", + "?}".fg(state.parser.colors().info), + "{?".fg(state.parser.colors().info) ) - .finish(), + ) ); return reports; } @@ -121,15 +116,11 @@ impl RegexRule for RawRule { util::escape_text('\\', "?}", content.as_str().trim_start().trim_end()); if processed.is_empty() { - reports.push( - Report::build(ReportKind::Warning, token.source(), content.start()) - .with_message("Empty Raw Code") - .with_label( - Label::new((token.source().clone(), content.range())) - .with_message("Raw code is empty") - .with_color(state.parser.colors().warning), - ) - .finish(), + report_warn!( + &mut reports, + token.source(), + "Empty Raw Code".into(), + span(content.range(), "Raw code is empty".into()) ); } processed @@ -140,15 +131,14 @@ impl RegexRule for RawRule { None => match self.properties.default() { Ok(properties) => properties, Err(e) => { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Raw Code") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!("Raw code is missing properties: {e}")) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Raw Code".into(), + span( + token.range.clone(), + format!("Raw code is missing properties: {e}") + ) ); return reports; } @@ -158,15 +148,11 @@ impl RegexRule for RawRule { util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { Err(e) => { - reports.push( - Report::build(ReportKind::Error, token.source(), props.start()) - .with_message("Invalid Raw Code Properties") - .with_label( - Label::new((token.source().clone(), props.range())) - .with_message(e) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Raw Code Properties".into(), + span(props.range(), e) ); return reports; } @@ -181,38 +167,33 @@ impl RegexRule for RawRule { Ok((_prop, kind)) => kind, Err(e) => match e { PropertyMapError::ParseError((prop, err)) => { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Raw Code Property") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!( - "Property `kind: {}` cannot be converted: {}", - prop.fg(state.parser.colors().info), - err.fg(state.parser.colors().error) - )) - .with_color(state.parser.colors().warning), + report_err!( + &mut reports, + token.source(), + "Invalid Raw Code Properties".into(), + span( + token.range.clone(), + format!( + "Property `kind: {}` cannot be converted: {}", + prop.fg(state.parser.colors().info), + err.fg(state.parser.colors().error) ) - .finish(), + ) ); return reports; } PropertyMapError::NotFoundError(err) => { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Code Property") - .with_label( - Label::new(( - token.source().clone(), - token.start() + 1..token.end(), - )) - .with_message(format!( - "Property `{}` is missing", - err.fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().warning), + report_err!( + &mut reports, + token.source(), + "Invalid Raw Code Properties".into(), + span( + token.range.clone(), + format!( + "Property `{}` is missing", + err.fg(state.parser.colors().info) ) - .finish(), + ) ); return reports; } @@ -232,15 +213,14 @@ impl RegexRule for RawRule { Semantics::from_source(token.source(), &state.shared.semantics) { let range = matches.get(0).unwrap().range(); - sems.add(range.start..range.start+2, tokens.raw_sep); - if let Some(props) = matches.get(1).map(|m| m.range()) - { + sems.add(range.start..range.start + 2, tokens.raw_sep); + if let Some(props) = matches.get(1).map(|m| m.range()) { sems.add(props.start - 1..props.start, tokens.raw_props_sep); sems.add(props.clone(), tokens.raw_props); sems.add(props.end..props.end + 1, tokens.raw_props_sep); } sems.add(matches.get(2).unwrap().range(), tokens.raw_content); - sems.add(range.end-2..range.end, tokens.raw_sep); + sems.add(range.end - 2..range.end, tokens.raw_sep); } reports @@ -297,7 +277,8 @@ mod tests { use crate::parser::langparser::LangParser; use crate::parser::parser::Parser; use crate::parser::source::SourceFile; - use crate::{validate_document, validate_semantics}; + use crate::validate_document; + use crate::validate_semantics; #[test] fn parser() { diff --git a/src/elements/reference.rs b/src/elements/reference.rs index 5b43a5a..e12db74 100644 --- a/src/elements/reference.rs +++ b/src/elements/reference.rs @@ -2,9 +2,6 @@ use std::collections::HashMap; use std::ops::Range; use std::rc::Rc; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use reference_style::ExternalReferenceStyle; use regex::Captures; use regex::Match; @@ -32,6 +29,8 @@ use crate::parser::util; use crate::parser::util::Property; use crate::parser::util::PropertyMap; use crate::parser::util::PropertyParser; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; #[derive(Debug)] pub struct InternalReference { @@ -186,39 +185,43 @@ impl ReferenceRule { fn parse_properties( &self, - colors: &ReportColors, + mut reports: &mut Vec, token: &Token, m: &Option, - ) -> Result, Range)>> { + ) -> Option { match m { None => match self.properties.default() { - Ok(properties) => Ok(properties), - Err(e) => Err( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Media Properties") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!("Media is missing required property: {e}")) - .with_color(colors.error), + Ok(properties) => Some(properties), + Err(e) => { + report_err!( + &mut reports, + token.source(), + "Invalid Reference Properties".into(), + span( + token.range.clone(), + format!("Reference is missing required property: {e}") ) - .finish(), - ), + ); + None + } }, Some(props) => { let processed = util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { - Err(e) => Err( - Report::build(ReportKind::Error, token.source(), props.start()) - .with_message("Invalid Media Properties") - .with_label( - Label::new((token.source().clone(), props.range())) - .with_message(e) - .with_color(colors.error), + Err(e) => { + report_err!( + &mut reports, + token.source(), + "Invalid Reference Properties".into(), + span( + props.range(), + e ) - .finish(), - ), - Ok(properties) => Ok(properties), + ); + None + }, + Ok(properties) => Some(properties), } } } @@ -241,7 +244,7 @@ impl RegexRule for ReferenceRule { document: &'a (dyn Document<'a> + 'a), token: Token, matches: Captures, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; let (refdoc, refname) = if let Some(refname_match) = matches.get(1) { @@ -252,14 +255,14 @@ impl RegexRule for ReferenceRule { match validate_refname(document, refname_match.as_str().split_at(sep + 1).1, false) { Err(err) => { - reports.push( - Report::build(ReportKind::Error, token.source(), refname_match.start()) - .with_message("Invalid Reference Refname") - .with_label( - Label::new((token.source().clone(), refname_match.range())) - .with_message(err), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Reference Refname".into(), + span( + refname_match.range(), + err + ) ); return reports; } @@ -270,14 +273,14 @@ impl RegexRule for ReferenceRule { { match validate_refname(document, refname_match.as_str(), false) { Err(err) => { - reports.push( - Report::build(ReportKind::Error, token.source(), refname_match.start()) - .with_message("Invalid Reference Refname") - .with_label( - Label::new((token.source().clone(), refname_match.range())) - .with_message(err), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Reference Refname".into(), + span( + refname_match.range(), + err + ) ); return reports; } @@ -289,13 +292,10 @@ impl RegexRule for ReferenceRule { }; // Properties - let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(2)) + let properties = match self.parse_properties(&mut reports, &token, &matches.get(2)) { - Ok(pm) => pm, - Err(report) => { - reports.push(report); - return reports; - } + Some(pm) => pm, + None => return reports, }; let caption = properties diff --git a/src/elements/script.rs b/src/elements/script.rs index 7c24178..9a05338 100644 --- a/src/elements/script.rs +++ b/src/elements/script.rs @@ -12,14 +12,13 @@ use crate::parser::source::VirtualSource; use crate::parser::util; use crate::parser::util::escape_source; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Lua; use regex::Captures; use regex::Regex; use std::ops::Range; use std::rc::Rc; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; use super::text::Text; @@ -95,7 +94,7 @@ impl RegexRule for ScriptRule { document: &'a dyn Document<'a>, token: Token, matches: Captures, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; let kernel_name = match matches.get(1) { @@ -104,15 +103,14 @@ impl RegexRule for ScriptRule { match ScriptRule::validate_kernel_name(state.parser.colors(), name.as_str()) { Ok(name) => name, Err(e) => { - reports.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Invalid kernel name") - .with_label( - Label::new((token.source(), name.range())) - .with_message(e) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Kernel Name".into(), + span( + name.range(), + e + ) ); return reports; } @@ -136,15 +134,14 @@ impl RegexRule for ScriptRule { ), '\\', ">@"); if source.content().is_empty() { - reports.push( - Report::build(ReportKind::Warning, token.source(), token.start()) - .with_message("Invalid kernel code") - .with_label( - Label::new((token.source(), script_range)) - .with_message("Kernel code is empty") - .with_color(state.parser.colors().warning), - ) - .finish(), + report_warn!( + &mut reports, + token.source(), + "Invalid Kernel Code".into(), + span( + script_range, + "Kernel code is empty".into(), + ) ); return reports; } @@ -157,15 +154,14 @@ impl RegexRule for ScriptRule { // Exec { if let Err(e) = chunk.exec() { - reports.push( - Report::build(ReportKind::Error, source.clone(), 0) - .with_message("Invalid kernel code") - .with_label( - Label::new((source.clone(), 0..source.content().len())) - .with_message(format!("Kernel execution failed:\n{}", e)) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + source.clone(), + "Invalid Kernel Code".into(), + span( + 0..source.content().len(), + format!("Kernel execution failed:\n{}", e) + ) ); return reports; } @@ -178,15 +174,14 @@ impl RegexRule for ScriptRule { Some(kind) => match self.validate_kind(state.parser.colors(), kind.as_str()) { Ok(kind) => kind, Err(msg) => { - reports.push( - Report::build(ReportKind::Error, token.source(), kind.start()) - .with_message("Invalid kernel code kind") - .with_label( - Label::new((token.source(), kind.range())) - .with_message(msg) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Kernel Code Kind".into(), + span( + kind.range(), + msg + ) ); return reports; } @@ -197,15 +192,14 @@ impl RegexRule for ScriptRule { // Eval { if let Err(e) = chunk.eval::<()>() { - reports.push( - Report::build(ReportKind::Error, source.clone(), 0) - .with_message("Invalid kernel code") - .with_label( - Label::new((source.clone(), 0..source.content().len())) - .with_message(format!("Kernel evaluation failed:\n{}", e)) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + source.clone(), + "Invalid Kernel Code".into(), + span( + 0..source.content().len(), + format!("Kernel evaluation failed:\n{}", e) + ) ); } } else @@ -245,18 +239,14 @@ impl RegexRule for ScriptRule { } } Err(e) => { - reports.push( - Report::build(ReportKind::Error, source.clone(), 0) - .with_message("Invalid kernel code") - .with_label( - Label::new((source.clone(), 0..source.content().len())) - .with_message(format!( - "Kernel evaluation failed:\n{}", - e - )) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + source.clone(), + "Invalid Kernel Code".into(), + span( + 0..source.content().len(), + format!("Kernel evaluation failed:\n{}", e) + ) ); } } diff --git a/src/elements/section.rs b/src/elements/section.rs index 1db17b5..3da3b89 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -13,9 +13,6 @@ use crate::parser::source::Source; use crate::parser::source::Token; use crate::parser::style::StyleHolder; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Error::BadArgument; use mlua::Function; use mlua::Lua; @@ -25,6 +22,8 @@ use section_style::SectionStyle; use std::ops::Range; use std::rc::Rc; use std::sync::Arc; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; use super::reference::InternalReference; @@ -183,22 +182,22 @@ impl RegexRule for SectionRule { document: &dyn Document, token: Token, matches: regex::Captures, - ) -> Vec, Range)>> { - let mut result = vec![]; + ) -> Vec { + let mut reports = vec![]; let section_depth = match matches.get(1) { Some(depth) => { if depth.len() > 6 { - result.push( - Report::build(ReportKind::Error, token.source(), depth.start()) - .with_message("Invalid section depth") - .with_label( - Label::new((token.source(), depth.range())) - .with_message(format!("Section is of depth {}, which is greather than {} (maximum depth allowed)", - depth.len().fg(state.parser.colors().info), - 6.fg(state.parser.colors().info))) - .with_color(state.parser.colors().error)) - .finish()); - return result; + report_err!( + &mut reports, + token.source(), + "Invalid Section Depth".into(), + span( + depth.range(), + format!("Section is of depth {}, which is greather than {} (maximum depth allowed)", + depth.len().fg(state.parser.colors().info), + 6.fg(state.parser.colors().info)) + ) + ); } depth.len() @@ -215,25 +214,27 @@ impl RegexRule for SectionRule { if let Some(elem_reference) = document.get_reference(refname.as_str()) { let elem = document.get_from_reference(&elem_reference).unwrap(); - result.push( - Report::build(ReportKind::Warning, token.source(), refname.start()) - .with_message("Duplicate reference name") - .with_label( - Label::new((token.source(), refname.range())) - .with_message(format!("Reference with name `{}` is already defined in `{}`", + + report_warn!( + &mut reports, + token.source(), + "Duplicate Reference Name".into(), + span( + refname.range(), + format!("Reference with name `{}` is already defined in `{}`. `{}` conflicts with previously defined reference to {}", refname.as_str().fg(state.parser.colors().highlight), - elem.location().source().name().as_str().fg(state.parser.colors().highlight))) - .with_message(format!("`{}` conflicts with previously defined reference to {}", + elem.location().source().name().as_str().fg(state.parser.colors().highlight), refname.as_str().fg(state.parser.colors().highlight), - elem.element_name().fg(state.parser.colors().highlight))) - .with_color(state.parser.colors().warning)) - .with_label( - Label::new((elem.location().source(), elem.location().start()..elem.location().end() )) - .with_message(format!("`{}` previously defined here", - refname.as_str().fg(state.parser.colors().highlight))) - .with_color(state.parser.colors().warning)) - .with_note("Previous reference was overwritten".to_string()) - .finish()); + elem.element_name().fg(state.parser.colors().highlight)) + ), + span( + elem.location().source(), + elem.location().start()..elem.location().end(), + format!("`{}` previously defined here", + refname.as_str().fg(state.parser.colors().highlight)) + ), + note("Previous reference was overwritten".into()) + ); } Some(refname.as_str().to_string()) }, @@ -247,19 +248,20 @@ impl RegexRule for SectionRule { "+" => section_kind::NO_TOC, "" => section_kind::NONE, _ => { - result.push( - Report::build(ReportKind::Error, token.source(), kind.start()) - .with_message("Invalid section numbering kind") - .with_label( - Label::new((token.source(), kind.range())) - .with_message(format!("Section numbering kind must be a combination of `{}` for unnumbered, and `{}` for non-listing; got `{}`", - "*".fg(state.parser.colors().info), - "+".fg(state.parser.colors().info), - kind.as_str().fg(state.parser.colors().highlight))) - .with_color(state.parser.colors().error)) - .with_help("Leave empty for a numbered listed section".to_string()) - .finish()); - return result; + report_err!( + &mut reports, + token.source(), + "Invalid Section Numbering Kind".into(), + span( + kind.range(), + format!("Section numbering kind must be a combination of `{}` for unnumbered, and `{}` for non-listing; got `{}`", + "*".fg(state.parser.colors().info), + "+".fg(state.parser.colors().info), + kind.as_str().fg(state.parser.colors().highlight)) + ), + help("Leave empty for a numbered listed section".into()) + ); + return reports; } }, _ => section_kind::NONE, @@ -278,31 +280,31 @@ impl RegexRule for SectionRule { if section_name.is_empty() // No name { - result.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Missing section name") - .with_label( - Label::new((token.source(), name.range())) - .with_message("Sections require a name before line end") - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Missing Section Name".into(), + span( + name.range(), + "Section name must be specified before line end".into() + ), ); - return result; + return reports; } // No spacing if split == 0 { - result.push( - Report::build(ReportKind::Warning, token.source(), name.start()) - .with_message("Missing section spacing") - .with_label( - Label::new((token.source(), name.range())) - .with_message("Sections require at least one whitespace before the section's name") - .with_color(state.parser.colors().warning)) - .with_help(format!("Add a space before `{}`", section_name.fg(state.parser.colors().highlight))) - .finish()); - return result; + report_err!( + &mut reports, + token.source(), + "Missing Section Spacing".into(), + span( + name.range(), + "Sections require at least one whitespace before the section's name".into() + ), + help(format!("Add a space before `{}`", section_name.fg(state.parser.colors().highlight))) + ); + return reports; } section_name.to_string() @@ -347,7 +349,7 @@ impl RegexRule for SectionRule { sems.add(matches.get(5).unwrap().range(), tokens.section_name); } - result + reports } fn register_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { diff --git a/src/elements/style.rs b/src/elements/style.rs index 6bf7ebd..a4a2452 100644 --- a/src/elements/style.rs +++ b/src/elements/style.rs @@ -14,9 +14,6 @@ use crate::parser::source::Token; use crate::parser::state::RuleState; use crate::parser::state::Scope; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Function; use regex::Captures; use regex::Regex; @@ -24,6 +21,8 @@ use std::cell::RefCell; use std::ops::Range; use std::rc::Rc; use std::sync::Arc; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; use super::paragraph::Paragraph; @@ -87,11 +86,11 @@ impl StyleState { impl RuleState for StyleState { fn scope(&self) -> Scope { Scope::PARAGRAPH } - fn on_remove<'a>( + fn on_remove( &self, state: &ParserState, document: &dyn Document, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; self.toggled @@ -114,27 +113,22 @@ impl RuleState for StyleState { ) }) .unwrap(); - - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Unterminated Style") - .with_label( - Label::new((token.source(), token.range.clone())) - .with_order(1) - .with_message(format!( - "Style {} starts here", - name.fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Unterminated Style".into(), + span( + token.range.clone(), + format!( + "Style {} starts here", + name.fg(state.parser.colors().info) ) - .with_label( - Label::new(paragraph_end) - .with_order(1) - .with_message("Paragraph ends here".to_string()) - .with_color(state.parser.colors().error), - ) - .with_note("Styles cannot span multiple documents (i.e @import)") - .finish(), + ), + span( + paragraph_end.1, + "Paragraph ends here".into() + ), + note("Styles cannot span multiple documents (i.e @import)".into()) ); }); @@ -182,7 +176,7 @@ impl RegexRule for StyleRule { document: &dyn Document, token: Token, _matches: Captures, - ) -> Vec, Range)>> { + ) -> Vec { let query = state.shared.rule_state.borrow().get(STATE_NAME); let style_state = match query { Some(state) => state, diff --git a/src/elements/tex.rs b/src/elements/tex.rs index 17b221e..476c2e3 100644 --- a/src/elements/tex.rs +++ b/src/elements/tex.rs @@ -10,9 +10,6 @@ use std::sync::Arc; use std::sync::Once; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use crypto::digest::Digest; use crypto::sha2::Sha512; use mlua::Function; @@ -41,6 +38,8 @@ use crate::parser::util::Property; use crate::parser::util::PropertyMap; use crate::parser::util::PropertyMapError; use crate::parser::util::PropertyParser; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; #[derive(Debug, PartialEq, Eq)] enum TexKind { @@ -266,39 +265,45 @@ impl TexRule { fn parse_properties( &self, + mut reports: &mut Vec, colors: &ReportColors, token: &Token, m: &Option, - ) -> Result, Range)>> { + ) -> Option { match m { None => match self.properties.default() { - Ok(properties) => Ok(properties), - Err(e) => Err( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Tex Properties") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!("Tex is missing required property: {e}")) - .with_color(colors.error), + Ok(properties) => Some(properties), + Err(e) => + { + report_err!( + &mut reports, + token.source(), + "Invalid Tex Properties".into(), + span( + token.range.clone(), + format!("Tex is missing required property: {e}") ) - .finish(), - ), + ); + None + } }, Some(props) => { let processed = util::escape_text('\\', "]", props.as_str().trim_start().trim_end()); match self.properties.parse(processed.as_str()) { - Err(e) => Err( - Report::build(ReportKind::Error, token.source(), props.start()) - .with_message("Invalid Tex Properties") - .with_label( - Label::new((token.source().clone(), props.range())) - .with_message(e) - .with_color(colors.error), + Err(e) => { + report_err!( + &mut reports, + token.source(), + "Invalid Tex Properties".into(), + span( + props.range(), + e ) - .finish(), - ), - Ok(properties) => Ok(properties), + ); + None + }, + Ok(properties) => Some(properties), } } } @@ -321,25 +326,24 @@ impl RegexRule for TexRule { document: &dyn Document, token: Token, matches: Captures, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; let tex_content = match matches.get(2) { // Unterminated `$` None => { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Unterminated Tex Code") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!( - "Missing terminating `{}` after first `{}`", - ["|$", "$"][index].fg(state.parser.colors().info), - ["$|", "$"][index].fg(state.parser.colors().info) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Unterminated Tex Code".into(), + span( + token.range.clone(), + format!( + "Missing terminating `{}` after first `{}`", + ["|$", "$"][index].fg(state.parser.colors().info), + ["$|", "$"][index].fg(state.parser.colors().info) ) - .finish(), + ) ); return reports; } @@ -351,15 +355,14 @@ impl RegexRule for TexRule { ); if processed.is_empty() { - reports.push( - Report::build(ReportKind::Warning, token.source(), content.start()) - .with_message("Empty Tex Code") - .with_label( - Label::new((token.source().clone(), content.range())) - .with_message("Tex code is empty") - .with_color(state.parser.colors().warning), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Empty Tex Code".into(), + span( + content.range(), + "Tex code is empty".into() + ) ); } processed @@ -367,13 +370,10 @@ impl RegexRule for TexRule { }; // Properties - let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(1)) + let properties = match self.parse_properties(&mut reports, state.parser.colors(), &token, &matches.get(1)) { - Ok(pm) => pm, - Err(report) => { - reports.push(report); - return reports; - } + Some(pm) => pm, + None => return reports, }; // Tex kind @@ -383,19 +383,19 @@ impl RegexRule for TexRule { Ok((_prop, kind)) => kind, Err(e) => match e { PropertyMapError::ParseError((prop, err)) => { - reports.push( - Report::build(ReportKind::Error, token.source(), token.start()) - .with_message("Invalid Tex Property") - .with_label( - Label::new((token.source().clone(), token.range.clone())) - .with_message(format!( - "Property `kind: {}` cannot be converted: {}", - prop.fg(state.parser.colors().info), - err.fg(state.parser.colors().error) - )) - .with_color(state.parser.colors().warning), + + report_err!( + &mut reports, + token.source(), + "Invalid Tex Property".into(), + span( + token.range.clone(), + format!( + "Property `kind: {}` cannot be converted: {}", + prop.fg(state.parser.colors().info), + err.fg(state.parser.colors().error) ) - .finish(), + ) ); return reports; } diff --git a/src/elements/text.rs b/src/elements/text.rs index edc13ff..a04a966 100644 --- a/src/elements/text.rs +++ b/src/elements/text.rs @@ -2,7 +2,6 @@ use std::any::Any; use std::ops::Range; use std::rc::Rc; -use ariadne::Report; use mlua::Function; use mlua::Lua; @@ -17,6 +16,7 @@ use crate::parser::rule::Rule; use crate::parser::source::Cursor; use crate::parser::source::Source; use crate::parser::source::Token; +use crate::parser::reports::*; #[derive(Debug)] pub struct Text { @@ -70,7 +70,7 @@ impl Rule for TextRule { _document: &dyn Document, _cursor: Cursor, _match_data: Box, - ) -> (Cursor, Vec, Range)>>) { + ) -> (Cursor, Vec) { panic!("Text cannot match"); } diff --git a/src/elements/variable.rs b/src/elements/variable.rs index 8ec6f8e..1fd7f7a 100644 --- a/src/elements/variable.rs +++ b/src/elements/variable.rs @@ -11,15 +11,14 @@ use crate::parser::rule::RegexRule; use crate::parser::source::Source; use crate::parser::source::Token; use ariadne::Fmt; -use ariadne::Label; -use ariadne::Report; -use ariadne::ReportKind; use mlua::Function; use mlua::Lua; use regex::Regex; use std::ops::Range; use std::rc::Rc; use std::str::FromStr; +use crate::parser::reports::*; +use crate::parser::reports::macros::*; #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum VariableKind { @@ -134,8 +133,8 @@ impl RegexRule for VariableRule { document: &dyn Document, token: Token, matches: regex::Captures, - ) -> Vec, Range)>> { - let mut result = vec![]; + ) -> Vec { + let mut reports = vec![]; // [Optional] variable kind let var_kind = match matches.get(1) { Some(kind) => { @@ -148,18 +147,18 @@ impl RegexRule for VariableRule { // Unknown kind specified if r.is_none() { - result.push( - Report::build(ReportKind::Error, token.source(), kind.start()) - .with_message("Unknown variable kind") - .with_label( - Label::new((token.source(), kind.range())) - .with_message(format!( - "Variable kind `{}` is unknown", - kind.as_str().fg(state.parser.colors().highlight) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Unknowm Variable Kind".into(), + span( + kind.range(), + format!( + "Variable kind `{}` is unknown", + kind.as_str().fg(state.parser.colors().highlight) ) - .with_help(format!( + ), + help(format!( "Leave empty for regular variables. Available variable kinds:{}", self.kinds.iter().skip(1).fold( "".to_string(), @@ -169,14 +168,12 @@ impl RegexRule for VariableRule { char.fg(state.parser.colors().highlight), name.fg(state.parser.colors().info) ) - .as_str() + .as_str() } ) - )) - .finish(), + )) ); - - return result; + return reports; } r.unwrap().0 @@ -188,21 +185,20 @@ impl RegexRule for VariableRule { Some(name) => match VariableRule::validate_name(state.parser.colors(), name.as_str()) { Ok(var_name) => var_name, Err(msg) => { - result.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Invalid variable name") - .with_label( - Label::new((token.source(), name.range())) - .with_message(format!( - "Variable name `{}` is not allowed. {msg}", - name.as_str().fg(state.parser.colors().highlight) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Invalid Variable Name".into(), + span( + name.range(), + format!( + "Variable name `{}` is not allowed. {msg}", + name.as_str().fg(state.parser.colors().highlight) ) - .finish(), + ), ); - return result; + return reports; } }, _ => panic!("Unknown variable name"), @@ -212,21 +208,20 @@ impl RegexRule for VariableRule { Some(value) => match VariableRule::validate_value(value.as_str()) { Ok(var_value) => var_value, Err(msg) => { - result.push( - Report::build(ReportKind::Error, token.source(), value.start()) - .with_message("Invalid variable value") - .with_label( - Label::new((token.source(), value.range())) - .with_message(format!( - "Variable value `{}` is not allowed. {msg}", - value.as_str().fg(state.parser.colors().highlight) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Invalid Variable Value".into(), + span( + value.range(), + format!( + "Variable value `{}` is not allowed. {msg}", + value.as_str().fg(state.parser.colors().highlight) ) - .finish(), + ), ); - return result; + return reports; } }, _ => panic!("Invalid variable value"), @@ -242,22 +237,21 @@ impl RegexRule for VariableRule { Ok(variable) => document.add_variable(variable), Err(msg) => { let m = matches.get(0).unwrap(); - result.push( - Report::build(ReportKind::Error, token.source(), m.start()) - .with_message("Unable to create variable") - .with_label( - Label::new((token.source(), m.start() + 1..m.end())) - .with_message(format!( + report_err!( + &mut reports, + token.source(), + "Unable to Create Variable".into(), + span( + m.start() + 1..m.end(), + format!( "Unable to create variable `{}`. {}", var_name.fg(state.parser.colors().highlight), msg - )) - .with_color(state.parser.colors().error), - ) - .finish(), + ) + ), ); - return result; + return reports; } } @@ -277,7 +271,7 @@ impl RegexRule for VariableRule { sems.add(value.clone(), tokens.variable_value); } - result + reports } fn register_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { @@ -346,98 +340,87 @@ impl RegexRule for VariableSubstitutionRule { document: &'a dyn Document<'a>, token: Token, matches: regex::Captures, - ) -> Vec, Range)>> { - let mut result = vec![]; + ) -> Vec { + let mut reports = vec![]; let variable = match matches.get(1) { Some(name) => { // Empty name if name.as_str().is_empty() { - result.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Empty variable name") - .with_label( - Label::new((token.source(), matches.get(0).unwrap().range())) - .with_message( - "Missing variable name for substitution".to_string(), - ) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Empty Variable Name".into(), + span( + name.range(), + "Missing variable name for substitution".into(), + ) ); - return result; + return reports; } // Leading spaces else if name.as_str().trim_start() != name.as_str() { - result.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Invalid variable name") - .with_label( - Label::new((token.source(), name.range())) - .with_message( - "Variable names contains leading spaces".to_string(), - ) - .with_color(state.parser.colors().error), - ) - .with_help("Remove leading spaces") - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Variable Name".into(), + span( + name.range(), + "Variable names contains leading spaces".into(), + ), + help("Remove leading spaces".into()) ); - return result; + return reports; } // Trailing spaces else if name.as_str().trim_end() != name.as_str() { - result.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Invalid variable name") - .with_label( - Label::new((token.source(), name.range())) - .with_message( - "Variable names contains trailing spaces".to_string(), - ) - .with_color(state.parser.colors().error), - ) - .with_help("Remove trailing spaces") - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Variable Name".into(), + span( + name.range(), + "Variable names contains trailing spaces".into(), + ), + help("Remove trailing spaces".into()) ); - return result; + return reports; } // Invalid name if let Err(msg) = VariableRule::validate_name(state.parser.colors(), name.as_str()) { - result.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Invalid variable name") - .with_label( - Label::new((token.source(), name.range())) - .with_message(msg) - .with_color(state.parser.colors().error), - ) - .finish(), + report_err!( + &mut reports, + token.source(), + "Invalid Variable Name".into(), + span( + name.range(), + msg + ) ); - return result; + return reports; } // Get variable match document.get_variable(name.as_str()) { None => { - result.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Unknown variable name") - .with_label( - Label::new((token.source(), name.range())) - .with_message(format!( - "Unable to find variable with name: `{}`", - name.as_str().fg(state.parser.colors().highlight) - )) - .with_color(state.parser.colors().error), + report_err!( + &mut reports, + token.source(), + "Unknown Variable Name".into(), + span( + name.range(), + format!( + "Unable to find variable with name: `{}`", + name.as_str().fg(state.parser.colors().highlight) ) - .finish(), + ) ); - return result; + return reports; } Some(var) => var, } @@ -456,6 +439,6 @@ impl RegexRule for VariableSubstitutionRule { sems.add(name.end..name.end + 1, tokens.variable_sub_sep); } - result + reports } } diff --git a/src/parser/customstyle.rs b/src/parser/customstyle.rs index 78e0712..2a90e43 100644 --- a/src/parser/customstyle.rs +++ b/src/parser/customstyle.rs @@ -1,14 +1,13 @@ use std::collections::HashMap; -use std::ops::Range; use std::rc::Rc; use std::ops::Deref; -use ariadne::Report; - use crate::document::document::Document; -use crate::parser::source::Source; use crate::parser::source::Token; +use crate::parser::reports::*; + + use super::parser::ParserState; #[derive(Debug, PartialEq, Eq)] @@ -28,13 +27,13 @@ pub trait CustomStyle: core::fmt::Debug { location: Token, state: &ParserState, document: &'a (dyn Document<'a> + 'a), - ) -> Vec, Range)>>; + ) -> Vec; fn on_end<'a>( &self, location: Token, state: &ParserState, document: &'a (dyn Document<'a> + 'a), - ) -> Vec, Range)>>; + ) -> Vec; } #[derive(Default)] diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 7cb3cf3..519af86 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1,5 +1,3 @@ -use ariadne::Label; -use ariadne::Report; use std::any::Any; use std::cell::RefCell; use std::collections::HashSet; @@ -9,6 +7,7 @@ use unicode_segmentation::UnicodeSegmentation; use super::customstyle::CustomStyleHolder; use super::layout::LayoutHolder; +use super::reports::Report; use super::rule::Rule; use super::source::Cursor; use super::source::Source; @@ -434,7 +433,9 @@ pub trait Parser { /// Handles the reports produced by parsing. The default is to output them /// to stderr, but you are free to modify it. - fn handle_reports(&self, reports: Vec, Range)>>) { + fn handle_reports(&self, reports: Vec) { + todo!(); // TODO + /* for mut report in reports { let mut sources: HashSet> = HashSet::new(); fn recurse_source(sources: &mut HashSet>, source: Rc) { @@ -483,5 +484,6 @@ pub trait Parser { }); report.eprint(ariadne::sources(cache)).unwrap() } + */ } } diff --git a/src/parser/reports.rs b/src/parser/reports.rs index bea0f8e..419b19b 100644 --- a/src/parser/reports.rs +++ b/src/parser/reports.rs @@ -3,7 +3,7 @@ use std::{ops::Range, rc::Rc}; use super::{parser::Parser, source::{Source, SourcePosition, Token}}; #[derive(Debug)] -enum ReportKind +pub enum ReportKind { Error, Warning, @@ -21,18 +21,20 @@ impl Into> for &ReportKind } #[derive(Debug)] -struct ReportSpan +pub struct ReportSpan { pub token: Token, pub message: String } #[derive(Debug)] -struct Report +pub struct Report { pub kind: ReportKind, pub source: Rc, pub message: String, + pub note: Option, + pub help: Option, pub spans: Vec, } @@ -86,36 +88,69 @@ impl Report } } -macro_rules! report_label { - ($spans:expr, $psource:expr,) => {{ }}; - ($spans:expr, $psource:expr, span($source:expr, $range:expr, $message:expr), $(, $($tail:tt)*)?) => {{ - $spans.push(ReportSpan { - token: Token::new($range, $source), - message: $message, - }); - report_label!($spans, $psource, $($($tail)*)?); - }}; - ($spans:expr, $psource:expr, span($range:expr, $message:expr) $(, $($tail:tt)*)?) => {{ - $spans.push(ReportSpan { - token: Token::new($range, $psource), - message: $message, - }); - report_label!($spans, $psource, $($($tail)*)?); - }} -} - +pub mod macros +{ + pub use super::*; #[macro_export] -macro_rules! report_err { - ($reports:expr, $source:expr, $message:expr, $($tail:tt)*) => {{ - let mut spans = Vec::new(); - report_label!(spans, $source.clone(), $($tail)*); - $reports.push(Report { - kind: ReportKind::Error, - source: $source, - message: $message, - spans, - }); - }} + macro_rules! report_label { + ($r:expr,) => {{ }}; + ($r:expr, span($source:expr, $range:expr, $message:expr), $(, $($tail:tt)*)?) => {{ + $r.spans.push(ReportSpan { + token: crate::parser::source::Token::Token::new($range, $source), + message: $message, + }); + report_label!($r, $($($tail)*)?); + }}; + ($r:expr, span($range:expr, $message:expr) $(, $($tail:tt)*)?) => {{ + $r.spans.push(ReportSpan { + token: crate::parser::source::Token::new($range, $r.source.clone()), + message: $message, + }); + report_label!($r, $($($tail)*)?); + }}; + ($r:expr, note($message:expr) $(, $($tail:tt)*)?) => {{ + $r.note = Some($message); + report_label!($r, $($($tail)*)?); + }}; + ($r:expr, help($message:expr) $(, $($tail:tt)*)?) => {{ + $r.help = Some($message); + report_label!($r, $($($tail)*)?); + }} + } + + #[macro_export] + macro_rules! report_err { + ($reports:expr, $source:expr, $message:expr, $($tail:tt)*) => {{ + let mut r = Report { + kind: ReportKind::Error, + source: $source, + message: $message, + note: None, + help: None, + spans: vec![], + }; + report_label!(r, $($tail)*); + $reports.push(r); + }} + } + + #[macro_export] + macro_rules! report_warn { + ($reports:expr, $source:expr, $message:expr, $($tail:tt)*) => {{ + let mut r = Report { + kind: ReportKind::Warning, + source: $source, + message: $message, + note: None, + help: None, + spans: vec![], + }; + report_label!(r, $($tail)*); + $reports.push(r); + }} + } + + pub use crate::*; } #[cfg(test)] @@ -140,7 +175,6 @@ Dolor )); let mut reports = vec![]; - //let la = report_label!(source.clone(), 5..9, "Msg".into()); report_err!(&mut reports, source.clone(), "Some message".into(), span(5..9, "Msg".into()), diff --git a/src/parser/rule.rs b/src/parser/rule.rs index f27ee2c..5759550 100644 --- a/src/parser/rule.rs +++ b/src/parser/rule.rs @@ -1,12 +1,12 @@ use super::layout::LayoutHolder; use super::parser::ParseMode; use super::parser::ParserState; +use super::reports::Report; use super::source::Cursor; use super::source::Source; use super::source::Token; use super::style::StyleHolder; use crate::document::document::Document; -use ariadne::Report; use downcast_rs::impl_downcast; use downcast_rs::Downcast; use mlua::Function; @@ -88,7 +88,7 @@ pub trait Rule: Downcast { document: &'a (dyn Document<'a> + 'a), cursor: Cursor, match_data: Box, - ) -> (Cursor, Vec, Range)>>); + ) -> (Cursor, Vec); /// Registers lua bindings fn register_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] } @@ -128,7 +128,7 @@ pub trait RegexRule { document: &'a (dyn Document<'a> + 'a), token: Token, matches: regex::Captures, - ) -> Vec, Range)>>; + ) -> Vec; fn register_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] } fn register_styles(&self, _holder: &mut StyleHolder) {} @@ -175,7 +175,7 @@ impl Rule for T { document: &'a (dyn Document<'a> + 'a), cursor: Cursor, match_data: Box, - ) -> (Cursor, Vec, Range)>>) { + ) -> (Cursor, Vec) { let content = cursor.source.content(); let index = match_data.downcast::().unwrap(); let re = &self.regexes()[*index]; diff --git a/src/parser/state.rs b/src/parser/state.rs index 4476755..79707cc 100644 --- a/src/parser/state.rs +++ b/src/parser/state.rs @@ -1,16 +1,14 @@ use std::cell::RefCell; use std::collections::HashMap; -use std::ops::Range; use std::rc::Rc; -use ariadne::Report; use downcast_rs::impl_downcast; use downcast_rs::Downcast; use crate::document::document::Document; use super::parser::ParserState; -use super::source::Source; +use super::reports::Report; /// Scope for state objects #[derive(PartialEq, PartialOrd, Debug)] @@ -30,11 +28,11 @@ pub trait RuleState: Downcast { fn scope(&self) -> Scope; /// Callback called when state goes out of scope - fn on_remove<'a>( + fn on_remove( &self, state: &ParserState, document: &dyn Document, - ) -> Vec, Range)>>; + ) -> Vec; } impl_downcast!(RuleState); @@ -72,7 +70,7 @@ impl RuleStateHolder { state: &ParserState, document: &dyn Document, scope: Scope, - ) -> Vec, Range)>> { + ) -> Vec { let mut reports = vec![]; self.states.retain(|_name, rule_state| {