From 72954cdad84fa0bb95e4c3ecec194a6696ad1acd Mon Sep 17 00:00:00 2001
From: ef3d0c3e <ef3d0c3e@pundalik.org>
Date: Wed, 23 Oct 2024 22:25:34 +0200
Subject: [PATCH] Reports refactor [1/2]
---
src/elements/blockquote.rs | 33 ++----
src/elements/customstyle.rs | 125 +++++++-------------
src/elements/elemstyle.rs | 82 ++++++-------
src/elements/layout.rs | 69 ++++++-----
src/elements/link.rs | 104 ++++++++---------
src/elements/list.rs | 35 ++----
src/elements/media.rs | 176 ++++++++++++++--------------
src/elements/raw.rs | 135 ++++++++++------------
src/elements/reference.rs | 96 ++++++++--------
src/elements/script.rs | 112 +++++++++---------
src/elements/section.rs | 136 +++++++++++-----------
src/elements/style.rs | 46 ++++----
src/elements/tex.rs | 128 ++++++++++-----------
src/elements/text.rs | 4 +-
src/elements/variable.rs | 223 +++++++++++++++++-------------------
src/parser/customstyle.rs | 11 +-
src/parser/parser.rs | 8 +-
src/parser/reports.rs | 100 ++++++++++------
src/parser/rule.rs | 8 +-
src/parser/state.rs | 10 +-
20 files changed, 757 insertions(+), 884 deletions(-)
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<dyn Any>,
- ) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
+ ) -> (Cursor, Vec<Report>) {
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::<Blockquote>().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<Report<(Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report<(Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<dyn Any>,
- ) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
+ ) -> (Cursor, Vec<Report>) {
let (style, end) = match_data
.downcast_ref::<(Rc<dyn CustomStyle>, 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<dyn Any>,
- ) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
+ ) -> (Cursor, Vec<Report>) {
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<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report>,
token: &Token,
layout_type: Rc<dyn LayoutType>,
properties: Option<Match>,
- ) -> Result<Option<Box<dyn Any>>, Report<'a, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Option<Box<dyn Any>> {
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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<dyn Any>,
- ) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
+ ) -> (Cursor, Vec<Report>) {
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<Report>,
token: &Token,
m: &Option<Match>,
- ) -> Result<PropertyMap, Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Option<PropertyMap> {
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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report>,
token: &Token,
m: &Option<Match>,
- ) -> Result<PropertyMap, Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Option<PropertyMap> {
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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
- let mut result = vec![];
+ ) -> Vec<Report> {
+ 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<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report<(Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<Report>,
colors: &ReportColors,
token: &Token,
m: &Option<Match>,
- ) -> Result<PropertyMap, Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Option<PropertyMap> {
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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
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<dyn Any>,
- ) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
+ ) -> (Cursor, Vec<Report>) {
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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
- let mut result = vec![];
+ ) -> Vec<Report> {
+ 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<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
- let mut result = vec![];
+ ) -> Vec<Report> {
+ 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<Report<(Rc<dyn Source>, Range<usize>)>>;
+ ) -> Vec<Report>;
fn on_end<'a>(
&self,
location: Token,
state: &ParserState,
document: &'a (dyn Document<'a> + 'a),
- ) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>>;
+ ) -> Vec<Report>;
}
#[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<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
+ fn handle_reports(&self, reports: Vec<Report>) {
+ todo!(); // TODO
+ /*
for mut report in reports {
let mut sources: HashSet<Rc<dyn Source>> = HashSet::new();
fn recurse_source(sources: &mut HashSet<Rc<dyn Source>>, source: Rc<dyn Source>) {
@@ -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<ariadne::ReportKind<'static>> 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<dyn Source>,
pub message: String,
+ pub note: Option<String>,
+ pub help: Option<String>,
pub spans: Vec<ReportSpan>,
}
@@ -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<dyn Any>,
- ) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
+ ) -> (Cursor, Vec<Report>);
/// 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<Report<'_, (Rc<dyn Source>, Range<usize>)>>;
+ ) -> Vec<Report>;
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<T: RegexRule + 'static> Rule for T {
document: &'a (dyn Document<'a> + 'a),
cursor: Cursor,
match_data: Box<dyn Any>,
- ) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
+ ) -> (Cursor, Vec<Report>) {
let content = cursor.source.content();
let index = match_data.downcast::<usize>().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<Report<'a, (Rc<dyn Source>, Range<usize>)>>;
+ ) -> Vec<Report>;
}
impl_downcast!(RuleState);
@@ -72,7 +70,7 @@ impl RuleStateHolder {
state: &ParserState,
document: &dyn Document,
scope: Scope,
- ) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+ ) -> Vec<Report> {
let mut reports = vec![];
self.states.retain(|_name, rule_state| {