Reports refactor [1/2]
This commit is contained in:
parent
f57173b9be
commit
72954cdad8
20 changed files with 757 additions and 884 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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![]
|
||||
|
|
|
@ -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
|
||||
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>)> {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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| {
|
||||
|
|
Loading…
Reference in a new issue