Add linenumber information to more errors
This commit is contained in:
parent
f92f8bfb66
commit
7c05cda33a
4 changed files with 60 additions and 12 deletions
|
@ -1,6 +1,7 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::value::AttrValue;
|
use crate::value::AttrValue;
|
||||||
use crate::with_text_pos_context;
|
use crate::with_text_pos_context;
|
||||||
|
@ -38,11 +39,23 @@ impl WidgetDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct WidgetUse {
|
pub struct WidgetUse {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub children: Vec<WidgetUse>,
|
pub children: Vec<WidgetUse>,
|
||||||
pub attrs: HashMap<String, AttrValue>,
|
pub attrs: HashMap<String, AttrValue>,
|
||||||
|
pub text_pos: Option<roxmltree::TextPos>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PositionData {
|
||||||
|
pub range: Range<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for WidgetUse {
|
||||||
|
fn eq(&self, other: &WidgetUse) -> bool {
|
||||||
|
self.name == other.name && self.children == other.children && self.attrs == other.attrs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetUse {
|
impl WidgetUse {
|
||||||
|
@ -51,18 +64,21 @@ impl WidgetUse {
|
||||||
name,
|
name,
|
||||||
children,
|
children,
|
||||||
attrs: HashMap::new(),
|
attrs: HashMap::new(),
|
||||||
|
..WidgetUse::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_xml_node(xml: XmlNode) -> Result<Self> {
|
pub fn from_xml_node(xml: XmlNode) -> Result<Self> {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref PATTERN: Regex = Regex::new("\\{\\{(.*)\\}\\}").unwrap();
|
static ref PATTERN: Regex = Regex::new("\\{\\{(.*)\\}\\}").unwrap();
|
||||||
};
|
};
|
||||||
match xml {
|
let text_pos = xml.text_pos();
|
||||||
|
let widget_use = match xml {
|
||||||
// TODO the matching here is stupid. This currently uses the inefficient function to parse simple single varrefs,
|
// TODO the matching here is stupid. This currently uses the inefficient function to parse simple single varrefs,
|
||||||
// TODO and does the regex match twice in the from_text_with_var_refs part
|
// TODO and does the regex match twice in the from_text_with_var_refs part
|
||||||
XmlNode::Text(text) if PATTERN.is_match(&text.text()) => Ok(WidgetUse::from_text_with_var_refs(&text.text())),
|
XmlNode::Text(text) if PATTERN.is_match(&text.text()) => WidgetUse::from_text_with_var_refs(&text.text()),
|
||||||
XmlNode::Text(text) => Ok(WidgetUse::simple_text(AttrValue::parse_string(text.text()))),
|
XmlNode::Text(text) => WidgetUse::simple_text(AttrValue::parse_string(text.text())),
|
||||||
XmlNode::Element(elem) => Ok(WidgetUse {
|
XmlNode::Element(elem) => WidgetUse {
|
||||||
name: elem.tag_name().to_string(),
|
name: elem.tag_name().to_string(),
|
||||||
children: with_text_pos_context! { elem => elem.children().map(WidgetUse::from_xml_node).collect::<Result<_>>()?}?,
|
children: with_text_pos_context! { elem => elem.children().map(WidgetUse::from_xml_node).collect::<Result<_>>()?}?,
|
||||||
attrs: elem
|
attrs: elem
|
||||||
|
@ -70,9 +86,11 @@ impl WidgetUse {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|attr| (attr.name().to_owned(), AttrValue::parse_string(attr.value().to_owned())))
|
.map(|attr| (attr.name().to_owned(), AttrValue::parse_string(attr.value().to_owned())))
|
||||||
.collect::<HashMap<_, _>>(),
|
.collect::<HashMap<_, _>>(),
|
||||||
}),
|
..WidgetUse::default()
|
||||||
|
},
|
||||||
XmlNode::Ignored(_) => Err(anyhow!("Failed to parse node {:?} as widget use", xml))?,
|
XmlNode::Ignored(_) => Err(anyhow!("Failed to parse node {:?} as widget use", xml))?,
|
||||||
}
|
};
|
||||||
|
Ok(widget_use.at_pos(text_pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn simple_text(text: AttrValue) -> Self {
|
pub fn simple_text(text: AttrValue) -> Self {
|
||||||
|
@ -80,6 +98,7 @@ impl WidgetUse {
|
||||||
name: "label".to_owned(),
|
name: "label".to_owned(),
|
||||||
children: vec![],
|
children: vec![],
|
||||||
attrs: hashmap! { "text".to_string() => text }, // TODO this hardcoded "text" is dumdum
|
attrs: hashmap! { "text".to_string() => text }, // TODO this hardcoded "text" is dumdum
|
||||||
|
..WidgetUse::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,9 +114,15 @@ impl WidgetUse {
|
||||||
.map(StringOrVarRef::to_attr_value)
|
.map(StringOrVarRef::to_attr_value)
|
||||||
.map(WidgetUse::simple_text)
|
.map(WidgetUse::simple_text)
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..WidgetUse::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn at_pos(mut self, text_pos: roxmltree::TextPos) -> Self {
|
||||||
|
self.text_pos = Some(text_pos);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_attr(&self, key: &str) -> Result<&AttrValue> {
|
pub fn get_attr(&self, key: &str) -> Result<&AttrValue> {
|
||||||
self.attrs
|
self.attrs
|
||||||
.get(key)
|
.get(key)
|
||||||
|
@ -181,6 +206,7 @@ mod test {
|
||||||
name: "label".to_owned(),
|
name: "label".to_owned(),
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
attrs: hashmap! { "text".to_owned() => expected_attr_value},
|
attrs: hashmap! { "text".to_owned() => expected_attr_value},
|
||||||
|
..WidgetUse::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -198,7 +224,8 @@ mod test {
|
||||||
children: vec![
|
children: vec![
|
||||||
WidgetUse::simple_text(expected_attr_value1),
|
WidgetUse::simple_text(expected_attr_value1),
|
||||||
WidgetUse::simple_text(expected_attr_value2),
|
WidgetUse::simple_text(expected_attr_value2),
|
||||||
]
|
],
|
||||||
|
..WidgetUse::default()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -227,6 +254,7 @@ mod test {
|
||||||
WidgetUse::new("child_widget".to_owned(), Vec::new()),
|
WidgetUse::new("child_widget".to_owned(), Vec::new()),
|
||||||
WidgetUse::simple_text(AttrValue::Concrete(PrimitiveValue::String("foo".to_owned()))),
|
WidgetUse::simple_text(AttrValue::Concrete(PrimitiveValue::String("foo".to_owned()))),
|
||||||
],
|
],
|
||||||
|
..WidgetUse::default()
|
||||||
};
|
};
|
||||||
assert_eq!(expected, WidgetUse::from_xml_node(xml).unwrap());
|
assert_eq!(expected, WidgetUse::from_xml_node(xml).unwrap());
|
||||||
}
|
}
|
||||||
|
@ -250,6 +278,7 @@ mod test {
|
||||||
"test".to_owned(),
|
"test".to_owned(),
|
||||||
)))],
|
)))],
|
||||||
attrs: HashMap::new(),
|
attrs: HashMap::new(),
|
||||||
|
..WidgetUse::default()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,12 @@ impl EwwConfig {
|
||||||
pub fn read_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
|
pub fn read_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
|
||||||
let content = std::fs::read_to_string(path)?;
|
let content = std::fs::read_to_string(path)?;
|
||||||
let document = roxmltree::Document::parse(&content)?;
|
let document = roxmltree::Document::parse(&content)?;
|
||||||
EwwConfig::from_xml_element(XmlNode::from(document.root_element()).as_element()?)
|
|
||||||
|
let start = std::time::Instant::now();
|
||||||
|
let result = EwwConfig::from_xml_element(XmlNode::from(document.root_element()).as_element()?);
|
||||||
|
let end = std::time::Instant::now();
|
||||||
|
dbg!(end - start);
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
||||||
|
|
|
@ -42,6 +42,10 @@ impl<'a, 'b> XmlNode<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn text_range(&self) -> std::ops::Range<usize> {
|
||||||
|
self.node().range()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn text_pos(&self) -> roxmltree::TextPos {
|
pub fn text_pos(&self) -> roxmltree::TextPos {
|
||||||
let document = self.node().document();
|
let document = self.node().document();
|
||||||
let range = self.node().range();
|
let range = self.node().range();
|
||||||
|
|
|
@ -61,7 +61,15 @@ pub fn build_gtk_widget(
|
||||||
};
|
};
|
||||||
let gtk_widget = match widget_to_gtk_widget(&mut bargs) {
|
let gtk_widget = match widget_to_gtk_widget(&mut bargs) {
|
||||||
Ok(Some(gtk_widget)) => gtk_widget,
|
Ok(Some(gtk_widget)) => gtk_widget,
|
||||||
result => return result,
|
result => {
|
||||||
|
return result.with_context(|| {
|
||||||
|
anyhow!(
|
||||||
|
"{}Error building widget {}",
|
||||||
|
bargs.widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(),
|
||||||
|
bargs.widget.name,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(gtk_widget) = gtk_widget.dynamic_cast_ref::<gtk::Container>() {
|
if let Some(gtk_widget) = gtk_widget.dynamic_cast_ref::<gtk::Container>() {
|
||||||
|
@ -70,7 +78,8 @@ pub fn build_gtk_widget(
|
||||||
let child_widget = element_to_gtk_thing(widget_definitions, bargs.eww_state, local_env, child);
|
let child_widget = element_to_gtk_thing(widget_definitions, bargs.eww_state, local_env, child);
|
||||||
let child_widget = child_widget.with_context(|| {
|
let child_widget = child_widget.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"error while building child '{:#?}' of '{}'",
|
"{}error while building child '{:#?}' of '{}'",
|
||||||
|
widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(),
|
||||||
&child,
|
&child,
|
||||||
>k_widget.get_widget_name()
|
>k_widget.get_widget_name()
|
||||||
)
|
)
|
||||||
|
@ -86,7 +95,8 @@ pub fn build_gtk_widget(
|
||||||
|
|
||||||
if !bargs.unhandled_attrs.is_empty() {
|
if !bargs.unhandled_attrs.is_empty() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"WARN: Unknown attribute used in {}: {}",
|
"{}WARN: Unknown attribute used in {}: {}",
|
||||||
|
widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(),
|
||||||
widget.name,
|
widget.name,
|
||||||
bargs.unhandled_attrs.join(", ")
|
bargs.unhandled_attrs.join(", ")
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue