From 3e232f71154c64c69d6efbe2766ba8ea4479f199 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 4 Feb 2022 13:18:58 -0800 Subject: [PATCH] Refine behavior of select_larger_syntax_node Co-Authored-By: Antonio Scandurra --- Cargo.lock | 8 +++--- crates/language/Cargo.toml | 2 +- crates/language/src/buffer.rs | 54 +++++++++++++++++++++++++++++------ crates/zed/Cargo.toml | 4 +-- 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce979fb313..f5e274cb81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5187,9 +5187,9 @@ dependencies = [ [[package]] name = "tree-sitter" -version = "0.20.1" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9394e9dbfe967b5f3d6ab79e302e78b5fb7b530c368d634ff3b8d67ede138bf1" +checksum = "4e34327f8eac545e3f037382471b2b19367725a242bba7bc45edb9efb49fe39a" dependencies = [ "cc", "regex", @@ -5206,9 +5206,9 @@ dependencies = [ [[package]] name = "tree-sitter-rust" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df540a493d754015d22eaf57c38f58804be3713a22f6062db983ec15f85c3c9" +checksum = "13470fafb7327a3acf96f5bc1013b5539a899a182f01c59b5af53f6b93195717" dependencies = [ "cc", "tree-sitter", diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index f0a3096a93..eef1a01054 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -40,7 +40,7 @@ serde_json = { version = "1", features = ["preserve_order"] } similar = "1.3" smallvec = { version = "1.6", features = ["union"] } smol = "1.2" -tree-sitter = "0.20.0" +tree-sitter = "0.20" tree-sitter-rust = { version = "0.20.0", optional = true } [dev-dependencies] diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 2efcbbf0d6..18e620fcd2 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -2139,17 +2139,53 @@ impl BufferSnapshot { } pub fn range_for_syntax_ancestor(&self, range: Range) -> Option> { - if let Some(tree) = self.tree.as_ref() { - let root = tree.root_node(); - let range = range.start.to_offset(self)..range.end.to_offset(self); - let mut node = root.descendant_for_byte_range(range.start, range.end); - while node.map_or(false, |n| n.byte_range() == range) { - node = node.unwrap().parent(); + let tree = self.tree.as_ref()?; + let range = range.start.to_offset(self)..range.end.to_offset(self); + let mut cursor = tree.root_node().walk(); + + // Descend to smallest leaf that touches or exceeds the start of the range. + while cursor.goto_first_child_for_byte(range.start).is_some() {} + + // Ascend to the smallest ancestor that strictly contains the range. + loop { + let node_range = cursor.node().byte_range(); + if node_range.start <= range.start + && node_range.end >= range.end + && node_range.len() > range.len() + { + break; + } + if !cursor.goto_parent() { + break; } - node.map(|n| n.byte_range()) - } else { - None } + + let left_node = cursor.node(); + + // For an empty range, try to find another node immediately to the right of the range. + if left_node.end_byte() == range.start { + let mut right_node = None; + while !cursor.goto_next_sibling() { + if !cursor.goto_parent() { + break; + } + } + + while cursor.node().start_byte() == range.start { + right_node = Some(cursor.node()); + if !cursor.goto_first_child() { + break; + } + } + + if let Some(right_node) = right_node { + if right_node.is_named() || !left_node.is_named() { + return Some(right_node.byte_range()); + } + } + } + + Some(left_node.byte_range()) } pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option> { diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 75713d02e3..2ac3df8c7f 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -89,8 +89,8 @@ thiserror = "1.0.29" time = "0.3" tiny_http = "0.8" toml = "0.5" -tree-sitter = "0.20.0" -tree-sitter-rust = "0.20.0" +tree-sitter = "0.20.4" +tree-sitter-rust = "0.20.1" tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" } url = "2.2"