compare_properties example block.

This commit is contained in:
Tom Alexander 2023-10-10 00:43:02 -04:00
parent ec98e1c3c5
commit bdfa050ee3
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 194 additions and 160 deletions

View File

@ -13,6 +13,10 @@ use super::util::get_property_numeric;
use super::util::get_property_quoted_string; use super::util::get_property_quoted_string;
use super::util::get_property_unquoted_atom; use super::util::get_property_unquoted_atom;
use crate::types::AstNode; use crate::types::AstNode;
use crate::types::CharOffsetInLine;
use crate::types::LineNumber;
use crate::types::RetainLabels;
use crate::types::SwitchNumberLines;
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum EmacsField<'s> { pub(crate) enum EmacsField<'s> {
@ -376,3 +380,115 @@ where
} }
Ok(ComparePropertiesResult::NoChange) Ok(ComparePropertiesResult::NoChange)
} }
pub(crate) fn compare_property_number_lines<
'b,
's,
'x,
'y,
R,
RG: Fn(R) -> Option<&'y SwitchNumberLines>,
>(
_source: &'s str,
emacs: &'b Token<'s>,
rust_node: R,
emacs_field: &'x str,
rust_value_getter: RG,
) -> Result<ComparePropertiesResult<'b, 's>, Box<dyn std::error::Error>> {
let number_lines = get_property(emacs, emacs_field)?;
let rust_value = rust_value_getter(rust_node);
match (number_lines, &rust_value) {
(None, None) => {}
(Some(number_lines), Some(rust_number_lines)) => {
let token_list = number_lines.as_list()?;
let number_type = token_list
.get(0)
.map(Token::as_atom)
.map_or(Ok(None), |r| r.map(Some))?
.ok_or(":number-lines should have a type.")?;
let number_value = token_list
.get(2)
.map(Token::as_atom)
.map_or(Ok(None), |r| r.map(Some))?
.map(|val| val.parse::<LineNumber>())
.map_or(Ok(None), |r| r.map(Some))?
.ok_or(":number-lines should have a value.")?;
match (number_type, number_value, rust_number_lines) {
("new", emacs_val, SwitchNumberLines::New(rust_val)) if emacs_val == *rust_val => {}
("continued", emacs_val, SwitchNumberLines::Continued(rust_val))
if emacs_val == *rust_val => {}
_ => {
let this_status = DiffStatus::Bad;
let message = Some(format!(
"{} mismatch (emacs != rust) {:?} != {:?}",
emacs_field, number_lines, rust_value
));
return Ok(ComparePropertiesResult::SelfChange(this_status, message));
}
}
}
_ => {
let this_status = DiffStatus::Bad;
let message = Some(format!(
"{} mismatch (emacs != rust) {:?} != {:?}",
emacs_field, number_lines, rust_value
));
return Ok(ComparePropertiesResult::SelfChange(this_status, message));
}
};
Ok(ComparePropertiesResult::NoChange)
}
pub(crate) fn compare_property_retain_labels<'b, 's, 'x, 'y, R, RG: Fn(R) -> &'y RetainLabels>(
_source: &'s str,
emacs: &'b Token<'s>,
rust_node: R,
emacs_field: &'x str,
rust_value_getter: RG,
) -> Result<ComparePropertiesResult<'b, 's>, Box<dyn std::error::Error + 's>> {
let rust_value = rust_value_getter(rust_node);
let retain_labels = get_property_unquoted_atom(emacs, ":retain-labels")?;
if let Some(retain_labels) = retain_labels {
if retain_labels == "t" {
match rust_value {
RetainLabels::Yes => {}
_ => {
let this_status = DiffStatus::Bad;
let message = Some(format!(
"{} mismatch (emacs != rust) {:?} != {:?}",
emacs_field, retain_labels, rust_value
));
return Ok(ComparePropertiesResult::SelfChange(this_status, message));
}
}
} else {
let retain_labels: CharOffsetInLine = get_property_numeric(emacs, ":retain-labels")?.expect("Cannot be None or else the earlier get_property_unquoted_atom would have been None.");
match (retain_labels, rust_value) {
(e, RetainLabels::Keep(r)) if e == *r => {}
_ => {
let this_status = DiffStatus::Bad;
let message = Some(format!(
"{} mismatch (emacs != rust) {:?} != {:?}",
emacs_field, retain_labels, rust_value
));
return Ok(ComparePropertiesResult::SelfChange(this_status, message));
}
}
}
} else {
match rust_value {
RetainLabels::No => {}
_ => {
let this_status = DiffStatus::Bad;
let message = Some(format!(
"{} mismatch (emacs != rust) {:?} != {:?}",
emacs_field, retain_labels, rust_value
));
return Ok(ComparePropertiesResult::SelfChange(this_status, message));
}
}
}
Ok(ComparePropertiesResult::NoChange)
}

View File

@ -10,8 +10,10 @@ use super::compare_field::compare_property_always_nil;
use super::compare_field::compare_property_boolean; use super::compare_field::compare_property_boolean;
use super::compare_field::compare_property_list_of_ast_nodes; use super::compare_field::compare_property_list_of_ast_nodes;
use super::compare_field::compare_property_list_of_quoted_string; use super::compare_field::compare_property_list_of_quoted_string;
use super::compare_field::compare_property_number_lines;
use super::compare_field::compare_property_numeric; use super::compare_field::compare_property_numeric;
use super::compare_field::compare_property_quoted_string; use super::compare_field::compare_property_quoted_string;
use super::compare_field::compare_property_retain_labels;
use super::compare_field::compare_property_set_of_quoted_string; use super::compare_field::compare_property_set_of_quoted_string;
use super::compare_field::compare_property_single_ast_node; use super::compare_field::compare_property_single_ast_node;
use super::compare_field::compare_property_unquoted_atom; use super::compare_field::compare_property_unquoted_atom;
@ -1944,166 +1946,73 @@ fn compare_comment_block<'b, 's>(
} }
fn compare_example_block<'b, 's>( fn compare_example_block<'b, 's>(
_source: &'s str, source: &'s str,
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b ExampleBlock<'s>, rust: &'b ExampleBlock<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error + 's>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error + 's>> {
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new();
let mut message = None; let mut message = None;
// TODO: Compare :caption assert_no_children(emacs, &mut this_status, &mut message)?;
// Compare name
let name = get_property_quoted_string(emacs, ":name")?;
if name.as_ref().map(String::as_str) != rust.name {
this_status = DiffStatus::Bad;
message = Some(format!(
"Name mismatch (emacs != rust) {:?} != {:?}",
name, rust.name
));
}
// Compare value for diff in compare_properties!(
let contents = get_property_quoted_string(emacs, ":value")?.unwrap_or(String::new()); source,
if contents != rust.contents { emacs,
this_status = DiffStatus::Bad; rust,
message = Some(format!( (
"Value mismatch (emacs != rust) {:?} != {:?}", EmacsField::Optional(":name"),
contents, rust.contents |r| r.name,
)); compare_property_quoted_string
} ),
(
// Compare switches EmacsField::Optional(":caption"),
let switches = get_property_quoted_string(emacs, ":switches")?; compare_identity,
match (switches.as_ref().map(String::as_str), rust.switches) { compare_noop
(None, None) => {} ),
(Some(""), None) => {} (
(None, Some("")) => { EmacsField::Required(":value"),
unreachable!("The organic parser would return a None instead of an empty string."); |r| Some(r.contents.as_str()),
} compare_property_quoted_string
(Some(e), Some(r)) if e == r => {} ),
_ => { (
this_status = DiffStatus::Bad; EmacsField::Required(":switches"),
message = Some(format!( |r| r.switches,
"Switches mismatch (emacs != rust) {:?} != {:?}", compare_property_quoted_string
switches, rust.switches ),
)); (
} EmacsField::Required(":number-lines"),
} |r| r.number_lines.as_ref(),
compare_property_number_lines
// Compare number-lines ),
let number_lines = get_property(emacs, ":number-lines")?; (
match (number_lines, &rust.number_lines) { EmacsField::Required(":preserve-indent"),
(None, None) => {} |r| r.preserve_indent,
(Some(number_lines), Some(rust_number_lines)) => { compare_property_numeric
let token_list = number_lines.as_list()?; ),
let number_type = token_list (
.get(0) EmacsField::Required(":retain-labels"),
.map(Token::as_atom) |r| &r.retain_labels,
.map_or(Ok(None), |r| r.map(Some))? compare_property_retain_labels
.ok_or(":number-lines should have a type.")?; ),
let number_value = token_list (
.get(2) EmacsField::Required(":use-labels"),
.map(Token::as_atom) |r| r.use_labels,
.map_or(Ok(None), |r| r.map(Some))? compare_property_boolean
.map(|val| val.parse::<LineNumber>()) ),
.map_or(Ok(None), |r| r.map(Some))? (
.ok_or(":number-lines should have a value.")?; EmacsField::Required(":label-fmt"),
match (number_type, number_value, rust_number_lines) { |r| r.label_format,
("new", emacs_val, SwitchNumberLines::New(rust_val)) if emacs_val == *rust_val => {} compare_property_quoted_string
("continued", emacs_val, SwitchNumberLines::Continued(rust_val)) )
if emacs_val == *rust_val => {} ) {
_ => { match diff {
this_status = DiffStatus::Bad; ComparePropertiesResult::NoChange => {}
message = Some(format!( ComparePropertiesResult::SelfChange(new_status, new_message) => {
"Number lines mismatch (emacs != rust) {:?} != {:?}", this_status = new_status;
number_lines, rust.number_lines message = new_message
));
}
} }
} ComparePropertiesResult::DiffEntry(diff_entry) => child_status.push(diff_entry),
_ => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Number lines mismatch (emacs != rust) {:?} != {:?}",
number_lines, rust.number_lines
));
}
};
// Compare preserve-indent
let preserve_indent: Option<CharOffsetInLine> =
get_property_numeric(emacs, ":preserve-indent")?;
if preserve_indent != rust.preserve_indent {
this_status = DiffStatus::Bad;
message = Some(format!(
"Prserve indent mismatch (emacs != rust) {:?} != {:?}",
preserve_indent, rust.preserve_indent
));
}
// Compare retain-labels
// retain-labels is t by default, nil if -r is set, or a number if -k and -r is set.
let retain_labels = get_property_unquoted_atom(emacs, ":retain-labels")?;
if let Some(retain_labels) = retain_labels {
if retain_labels == "t" {
match rust.retain_labels {
RetainLabels::Yes => {}
_ => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Retain labels mismatch (emacs != rust) {:?} != {:?}",
retain_labels, rust.retain_labels
));
}
}
} else {
let retain_labels: CharOffsetInLine = get_property_numeric(emacs, ":retain-labels")?.expect("Cannot be None or else the earlier get_property_unquoted_atom would have been None.");
match (retain_labels, &rust.retain_labels) {
(e, RetainLabels::Keep(r)) if e == *r => {}
_ => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Retain labels mismatch (emacs != rust) {:?} != {:?}",
retain_labels, rust.retain_labels
));
}
}
}
} else {
match rust.retain_labels {
RetainLabels::No => {}
_ => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Retain labels mismatch (emacs != rust) {:?} != {:?}",
retain_labels, rust.retain_labels
));
}
}
}
// Compare use-labels
let use_labels = get_property_boolean(emacs, ":use-labels")?;
if use_labels != rust.use_labels {
this_status = DiffStatus::Bad;
message = Some(format!(
"Use labels mismatch (emacs != rust) {:?} != {:?}",
use_labels, rust.use_labels
));
}
// Compare label-fmt
let label_format = get_property_quoted_string(emacs, ":label-fmt")?;
match (label_format.as_ref(), rust.label_format) {
(None, None) => {}
(Some(emacs_label_format), Some(rust_label_format))
if emacs_label_format == rust_label_format => {}
_ => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Label format mismatch (emacs != rust) {:?} != {:?}",
label_format, rust.label_format
));
} }
} }
@ -2111,7 +2020,7 @@ fn compare_example_block<'b, 's>(
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
message, message,
children: Vec::new(), children: child_status,
rust_source: rust.get_source(), rust_source: rust.get_source(),
emacs_token: emacs, emacs_token: emacs,
} }

View File

@ -16,6 +16,7 @@ use nom::combinator::verify;
use nom::multi::many0; use nom::multi::many0;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use nom::InputTake;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
@ -160,7 +161,20 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
) -> Res<OrgSource<'s>, ExampleBlock<'s>> { ) -> Res<OrgSource<'s>, ExampleBlock<'s>> {
let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let (remaining, _) = lesser_block_begin("example")(context, remaining)?; let (remaining, _) = lesser_block_begin("example")(context, remaining)?;
let (remaining, parameters) = opt(tuple((space1, example_switches)))(remaining)?; let (remaining, parameters) = opt(alt((
map(tuple((space1, example_switches)), |(_, switches)| switches),
map(space1, |ws: OrgSource<'_>| {
let source = ws.take(0);
ExampleSrcSwitches {
source: source.into(),
number_lines: None,
retain_labels: RetainLabels::Yes,
preserve_indent: None,
use_labels: true,
label_format: None,
}
}),
)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let lesser_block_end_specialized = lesser_block_end("example"); let lesser_block_end_specialized = lesser_block_end("example");
let contexts = [ let contexts = [
@ -174,7 +188,6 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
let parser_context = context.with_additional_node(&contexts[0]); let parser_context = context.with_additional_node(&contexts[0]);
let parser_context = parser_context.with_additional_node(&contexts[1]); let parser_context = parser_context.with_additional_node(&contexts[1]);
let parser_context = parser_context.with_additional_node(&contexts[2]); let parser_context = parser_context.with_additional_node(&contexts[2]);
let parameters = parameters.map(|(_, parameters)| parameters);
let (remaining, contents) = content(&parser_context, remaining)?; let (remaining, contents) = content(&parser_context, remaining)?;
let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?; let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?;
@ -185,11 +198,7 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
let (switches, number_lines, preserve_indent, retain_labels, use_labels, label_format) = { let (switches, number_lines, preserve_indent, retain_labels, use_labels, label_format) = {
if let Some(parameters) = parameters { if let Some(parameters) = parameters {
( (
if parameters.source.len() == 0 { Some(parameters.source),
None
} else {
Some(parameters.source)
},
parameters.number_lines, parameters.number_lines,
parameters.preserve_indent, parameters.preserve_indent,
parameters.retain_labels, parameters.retain_labels,