From 172d72aa4620bdc0b7a58eacf0e045d053384930 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 30 Dec 2023 17:09:12 -0500 Subject: [PATCH] Implement src block. --- src/wasm/src_block.rs | 71 ++++++++++++++++++++++++++++++- src/wasm_test/compare.rs | 91 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 2 deletions(-) diff --git a/src/wasm/src_block.rs b/src/wasm/src_block.rs index 6aac926a..620a7d51 100644 --- a/src/wasm/src_block.rs +++ b/src/wasm/src_block.rs @@ -6,13 +6,55 @@ use super::macros::to_wasm; use super::to_wasm::ToWasm; use super::AdditionalProperties; use crate::compare::ElispFact; +use crate::types::CharOffsetInLine; +use crate::types::GetAffiliatedKeywords; +use crate::types::LineNumber; +use crate::types::RetainLabels; use crate::types::SrcBlock; +use crate::types::SwitchNumberLines; use crate::wasm::to_wasm::ToWasmStandardProperties; #[derive(Debug, Serialize, Deserialize)] pub struct WasmSrcBlock { #[serde(flatten)] pub(crate) additional_properties: AdditionalProperties, + pub(crate) language: Option, + pub(crate) value: String, + pub(crate) switches: Option, + pub(crate) parameters: Option, + #[serde(rename = "number-lines")] + pub(crate) number_lines: Option, + #[serde(rename = "preserve-indent")] + pub(crate) preserve_indent: Option, + #[serde(rename = "retain-labels")] + pub(crate) retain_labels: WasmRetainLabels, + #[serde(rename = "use-labels")] + pub(crate) use_labels: bool, + #[serde(rename = "label-fmt")] + pub(crate) label_format: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] +enum WasmRetainLabels { + YesNo(bool), + Keep(CharOffsetInLine), +} + +#[derive(Debug, Serialize, Deserialize)] +enum WasmNumberLines { + #[serde(rename = "new")] + New(LineNumber), + #[serde(rename = "continued")] + continued(LineNumber), +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename = "number-lines")] +#[serde(tag = "number-lines")] +struct WasmNumberLinesWrapper { + #[serde(flatten)] + inner: WasmNumberLines, } to_wasm!( @@ -21,12 +63,37 @@ to_wasm!( original, wasm_context, { WasmAstNode::SrcBlock(original) }, - { "TODO".into() }, + { "src-block".into() }, { + let additional_properties = original + .get_affiliated_keywords() + .to_wasm(wasm_context.clone())?; + Ok(( Vec::new(), WasmSrcBlock { - additional_properties: AdditionalProperties::default(), + additional_properties, + language: original.language.map(|s| s.to_owned()), + value: original.value.to_owned(), + switches: original.switches.map(|s| s.to_owned()), + parameters: original.parameters.map(|s| s.to_owned()), + number_lines: match original.number_lines { + None => None, + Some(SwitchNumberLines::New(n)) => Some(WasmNumberLinesWrapper { + inner: WasmNumberLines::New(n), + }), + Some(SwitchNumberLines::Continued(n)) => Some(WasmNumberLinesWrapper { + inner: WasmNumberLines::continued(n), + }), + }, + preserve_indent: original.preserve_indent, + retain_labels: match original.retain_labels { + RetainLabels::No => WasmRetainLabels::YesNo(false), + RetainLabels::Yes => WasmRetainLabels::YesNo(true), + RetainLabels::Keep(n) => WasmRetainLabels::Keep(n), + }, + use_labels: original.use_labels, + label_format: original.label_format.map(|s| s.to_owned()), }, )) } diff --git a/src/wasm_test/compare.rs b/src/wasm_test/compare.rs index bb501229..d4897d96 100644 --- a/src/wasm_test/compare.rs +++ b/src/wasm_test/compare.rs @@ -54,6 +54,10 @@ fn compare_json_value<'b, 's>( // We hit an object tree additional property. compare_object_tree(source, el, wasm) } + (serde_json::Value::Object(wasm), Token::List(el)) if wasm.contains_key("number-lines") => { + // We hit an object tree additional property. + compare_number_lines(source, el, wasm) + } (serde_json::Value::Object(w), Token::TextWithProperties(e)) if is_plain_text(w) => { compare_plain_text(source, e, w) } @@ -628,6 +632,93 @@ fn compare_object_tree<'e, 's, 'w>( Ok(result) } +fn compare_number_lines<'e, 's, 'w>( + source: &'s str, + emacs: &'e Vec>, + wasm: &'w serde_json::Map, +) -> Result, Box> { + let mut result = WasmDiffResult::default(); + let mut emacs_iter = emacs.iter(); + let emacs_directive = emacs_iter + .next() + .ok_or("Emacs number lines should have 3 children.")? + .as_atom()?; + let emacs_number: i64 = emacs_iter + .skip(1) + .next() + .ok_or("Emacs number lines should have 3 children.")? + .as_atom()? + .parse()?; + if wasm.contains_key("new") { + let wasm_number = wasm + .get("new") + .ok_or(r#"Wasm number lines should have a "new" attribute."#)? + .as_i64() + .ok_or(r#"Wasm number lines "new" attribute should be a number."#)?; + if emacs_directive != "new" { + result.status.push(WasmDiffStatus::Bad( + format!( + "Number lines directive mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).", + emacs = emacs_directive, + wasm = "new" + ) + .into(), + )); + return Ok(result); + } + if emacs_number != wasm_number { + result.status.push(WasmDiffStatus::Bad( + format!( + "Number lines number mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).", + emacs = emacs_number, + wasm = wasm_number + ) + .into(), + )); + return Ok(result); + } + } else if wasm.contains_key("continued") { + let wasm_number = wasm + .get("continued") + .ok_or(r#"Wasm number lines should have a "continued" attribute."#)? + .as_i64() + .ok_or(r#"Wasm number lines "continued" attribute should be a number."#)?; + if emacs_directive != "continued" { + result.status.push(WasmDiffStatus::Bad( + format!( + "Number lines directive mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).", + emacs = emacs_directive, + wasm = "continued" + ) + .into(), + )); + return Ok(result); + } + if emacs_number != wasm_number { + result.status.push(WasmDiffStatus::Bad( + format!( + "Number lines number mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).", + emacs = emacs_number, + wasm = wasm_number + ) + .into(), + )); + return Ok(result); + } + } else { + result.status.push(WasmDiffStatus::Bad( + format!( + "Unrecognized number lines directive. Wasm=({wasm:?}).", + wasm = wasm + ) + .into(), + )); + return Ok(result); + } + + Ok(result) +} + fn is_plain_text<'e, 's, 'w>(wasm: &'w serde_json::Map) -> bool { if let Some(serde_json::Value::String(node_type)) = wasm.get("ast-node") { node_type == "plain-text"