Compare plain text AST nodes.

This commit is contained in:
Tom Alexander 2023-12-29 17:24:38 -05:00
parent 037caf369c
commit 777c756a7f
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 125 additions and 1 deletions

View File

@ -16,6 +16,7 @@ pub(crate) use compare_field::EmacsField;
pub(crate) use elisp_fact::ElispFact;
pub use sexp::sexp;
pub(crate) use sexp::unquote;
pub(crate) use sexp::TextWithProperties;
pub use sexp::Token;
pub(crate) use util::get_emacs_standard_properties;
pub(crate) use util::get_property;

View File

@ -21,7 +21,7 @@ to_wasm!(
original,
wasm_context,
{ WasmAstNode::PlainText(original) },
{ "TODO".into() },
{ "plain-text".into() },
{
Ok((
Vec::new(),

View File

@ -5,9 +5,11 @@ use super::diff::WasmDiffResult;
use super::diff::WasmDiffStatus;
use crate::compare::get_emacs_standard_properties;
use crate::compare::maybe_token_to_usize;
use crate::compare::unquote;
use crate::compare::ElispFact;
use crate::compare::EmacsField;
use crate::compare::EmacsStandardProperties;
use crate::compare::TextWithProperties;
use crate::compare::Token;
use crate::wasm::WasmAngleLink;
use crate::wasm::WasmAstNode;
@ -109,6 +111,9 @@ fn compare_json_value<'b, 's>(
{
compare_optional_pair(source, e, wasm)
}
(serde_json::Value::Object(w), Token::TextWithProperties(e)) if is_plain_text(w) => {
compare_plain_text(source, e, w)
}
(serde_json::Value::Null, Token::Atom(_)) => todo!(),
(serde_json::Value::Null, Token::List(_)) => todo!(),
(serde_json::Value::Null, Token::TextWithProperties(_)) => todo!(),
@ -478,6 +483,124 @@ fn compare_optional_pair<'e, 's, 'w>(
Ok(result)
}
fn is_plain_text<'e, 's, 'w>(wasm: &'w serde_json::Map<String, serde_json::Value>) -> bool {
if let Some(serde_json::Value::String(node_type)) = wasm.get("ast-node") {
node_type == "plain-text"
} else {
false
}
}
fn compare_plain_text<'e, 's, 'w>(
source: &'s str,
emacs: &'e TextWithProperties<'s>,
wasm: &'w serde_json::Map<String, serde_json::Value>,
) -> Result<WasmDiffResult<'s>, Box<dyn std::error::Error>> {
let mut result = WasmDiffResult::default();
if !is_plain_text(wasm) {
result.status.push(WasmDiffStatus::Bad(
format!(
"AST node type mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).",
emacs = emacs,
wasm = wasm,
)
.into(),
));
return Ok(result);
}
let emacs_text = unquote(emacs.text)?;
let wasm_standard_properties = wasm
.get("standard-properties")
.ok_or(r#"Wasm AST nodes should have a "standard-properties" attribute."#)?
.as_object()
.ok_or(r#"Wasm ast node "standard-properties" attribute should be an object."#)?;
let wasm_begin = {
if let Some(serde_json::Value::Number(begin)) = wasm_standard_properties.get("begin") {
begin
.as_u64()
.map(|w| w as usize)
.ok_or("Begin should be a number.")?
} else {
result.status.push(WasmDiffStatus::Bad(
format!(
"AST node type mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).",
emacs = emacs,
wasm = wasm,
)
.into(),
));
return Ok(result);
}
};
let wasm_end = {
if let Some(serde_json::Value::Number(end)) = wasm_standard_properties.get("end") {
end.as_u64()
.map(|w| w as usize)
.ok_or("End should be a number.")?
} else {
result.status.push(WasmDiffStatus::Bad(
format!(
"AST node type mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).",
emacs = emacs,
wasm = wasm,
)
.into(),
));
return Ok(result);
}
};
let wasm_text: String = source
.chars()
.skip(wasm_begin - 1)
.take(wasm_end - wasm_begin)
.collect();
if wasm_text != emacs_text {
result.status.push(WasmDiffStatus::Bad(
format!(
"Text mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).",
emacs = emacs_text,
wasm = wasm_text,
)
.into(),
));
return Ok(result);
}
let emacs_start = emacs
.properties
.first()
.map(|t| t.as_atom())
.map_or(Ok(None), |r| r.map(Some))?;
if emacs_start != Some("0") {
result.status.push(WasmDiffStatus::Bad(
format!(
"Text should start at offset 0. Emacs=({emacs:?}) Wasm=({wasm:?}).",
emacs = emacs,
wasm = wasm,
)
.into(),
));
}
let emacs_end = emacs
.properties
.get(1)
.map(|t| t.as_atom())
.map_or(Ok(None), |r| r.map(Some))?;
if emacs_end != Some((wasm_end - wasm_begin).to_string().as_str()) {
result.status.push(WasmDiffStatus::Bad(
format!(
"Text end mismatch. Emacs=({emacs:?}) Wasm=({wasm:?}).",
emacs = emacs_end,
wasm = wasm_end - wasm_begin,
)
.into(),
));
}
Ok(result)
}
// pub fn old_wasm_compare_document<'b, 's, 'p>(
// source: &'s str,
// emacs: &'b Token<'s>,