diff --git a/Cargo.lock b/Cargo.lock index 89240f4..9989f5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -278,6 +278,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.14" @@ -453,6 +459,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "heck" version = "0.4.1" @@ -487,6 +499,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "inflections" version = "1.1.1" @@ -803,6 +825,7 @@ version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ + "indexmap", "itoa", "memchr", "serde", @@ -839,6 +862,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8e2fb0f499abb4d162f2bedad68f5ef91a1682b5a03596ddb67efd37768d100" +[[package]] +name = "streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" + [[package]] name = "strsim" version = "0.11.1" @@ -966,32 +995,42 @@ dependencies = [ [[package]] name = "tree-sitter" -version = "0.22.6" +version = "0.26.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7cc499ceadd4dcdf7ec6d4cbc34ece92c3fa07821e287aedecd4416c516dca" +checksum = "3c343ed63e3f5c64d1acdecb5d2c13d4e169cb5fde0052106ebaa6c6f27f9e55" dependencies = [ "cc", "regex", + "regex-syntax 0.8.11", + "serde_json", + "streaming-iterator", + "tree-sitter-language", ] [[package]] name = "tree-sitter-html" -version = "0.20.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8766b5ad3721517f8259e6394aefda9c686aebf7a8c74ab8624f2c3b46902fd5" +checksum = "261b708e5d92061ede329babaaa427b819329a9d427a1d710abb0f67bbef63ee" dependencies = [ "cc", - "tree-sitter", + "tree-sitter-language", ] +[[package]] +name = "tree-sitter-language" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782" + [[package]] name = "tree-sitter-rust" -version = "0.21.2" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "277690f420bf90741dea984f3da038ace46c4fe6047cba57a66822226cde1c93" +checksum = "439e577dbe07423ec2582ac62c7531120dbfccfa6e5f92406f93dd271a120e45" dependencies = [ "cc", - "tree-sitter", + "tree-sitter-language", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4bd1bad..dc08fb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,9 @@ repository = "https://github.com/bounded-systems/git-ast" # its `Map` is a `BTreeMap` (keys sorted) with deterministic scalar formatting — # exactly the value-level normalization a canonical form needs. [dependencies] -tree-sitter = "0.22" -tree-sitter-rust = "0.21" -tree-sitter-html = "0.20" +tree-sitter = "0.26" +tree-sitter-rust = "0.24" +tree-sitter-html = "0.23" serde_json = "1" # The Gherkin suite (tests/features/*.feature) executes the README's claims diff --git a/src/html.rs b/src/html.rs index 4daf1ec..65796fb 100644 --- a/src/html.rs +++ b/src/html.rs @@ -25,7 +25,7 @@ use crate::Error; fn parse(source: &[u8]) -> Result { let mut parser = Parser::new(); parser - .set_language(&tree_sitter_html::language()) + .set_language(&tree_sitter_html::LANGUAGE.into()) .map_err(|e| Error::Parsing(format!("loading HTML grammar: {e}")))?; parser .parse(source, None) @@ -175,7 +175,8 @@ fn extract_attr_value(node: Node, src: &[u8]) -> String { // use `node` again in the fallback path. let found: Option = { let mut c = node.walk(); - let x = node.named_children(&mut c) + let x = node + .named_children(&mut c) .find(|n| n.kind() == "attribute_value") .and_then(|n| n.utf8_text(src).ok()) .map(str::to_string); @@ -425,8 +426,7 @@ fn element_to_def(node: Node, src: &[u8]) -> Option { let mut cursor = node.walk(); let children: Vec = node.children(&mut cursor).collect(); drop(cursor); - let (tag_node, has_body) = if let Some(&st) = - children.iter().find(|n| n.kind() == "start_tag") + let (tag_node, has_body) = if let Some(&st) = children.iter().find(|n| n.kind() == "start_tag") { (st, true) } else if let Some(&sc) = children.iter().find(|n| n.kind() == "self_closing_tag") { @@ -443,7 +443,11 @@ fn element_to_def(node: Node, src: &[u8]) -> Option { .get("role") .and_then(|r| aria_kind(r)) .or_else(|| implicit_role(&tag_name))?; - let text = if has_body { collect_text(node, src) } else { String::new() }; + let text = if has_body { + collect_text(node, src) + } else { + String::new() + }; let name = accessible_name(&attrs, &text).unwrap_or_default(); Some(make_def(kind, &name, &tag_name, &attrs)) } @@ -488,12 +492,7 @@ fn self_closing_to_def(node: Node, src: &[u8]) -> Option { /// so two elements that differ only in label share the same shape. const NAME_ATTRS: &[&str] = &["aria-label", "title", "alt"]; -fn make_def( - kind: &'static str, - name: &str, - tag: &str, - attrs: &BTreeMap, -) -> Def { +fn make_def(kind: &'static str, name: &str, tag: &str, attrs: &BTreeMap) -> Def { let attr_str: String = attrs .iter() .map(|(k, v)| format!("{k}={v}")) @@ -571,7 +570,10 @@ mod tests { #[test] fn values_double_quoted() { let out = canon(r#"link"#); - assert!(out.contains(r#"href="/page""#), "single quotes not converted: {out}"); + assert!( + out.contains(r#"href="/page""#), + "single quotes not converted: {out}" + ); } #[test] @@ -599,7 +601,10 @@ mod tests { fn script_and_style_preserved_verbatim() { let src = ""; let out = canon(src); - assert!(out.contains("var x={b:1,a:2};"), "script was modified: {out}"); + assert!( + out.contains("var x={b:1,a:2};"), + "script was modified: {out}" + ); } // ── inspect ─────────────────────────────────────────────────────────────── @@ -704,7 +709,11 @@ mod tests { fn subtree_hashes_nonempty_for_semantic_elements() { let ds = defs(r#""#); for d in &ds { - assert!(!d.subtree_hashes.is_empty(), "no subtree hashes for {}", d.kind); + assert!( + !d.subtree_hashes.is_empty(), + "no subtree hashes for {}", + d.kind + ); } } } diff --git a/src/printer.rs b/src/printer.rs index f2d355f..1008eb3 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -66,7 +66,7 @@ pub fn canonicalize(source: &[u8]) -> Result, Error> { fn parse(source: &[u8]) -> Result { let mut parser = Parser::new(); parser - .set_language(&tree_sitter_rust::language()) + .set_language(&tree_sitter_rust::LANGUAGE.into()) .map_err(|e| Error::Parsing(format!("loading Rust grammar: {e}")))?; let tree = parser .parse(source, None)