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