From 15ab18dd150af56e6871f72e40ba336e55a3ff85 Mon Sep 17 00:00:00 2001 From: Domenic Quirl Date: Fri, 3 Sep 2021 22:25:08 +0200 Subject: [PATCH] add `SyntaxToken::text_eq` --- src/green/token.rs | 5 +++++ src/syntax/token.rs | 14 ++++++++++++++ tests/it/basic.rs | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/src/green/token.rs b/src/green/token.rs index 01c1cc5..74f40db 100644 --- a/src/green/token.rs +++ b/src/green/token.rs @@ -69,6 +69,11 @@ impl GreenToken { pub fn text_len(&self) -> TextSize { self.data().text_len } + + #[inline] + pub(crate) fn text_key(&self) -> Spur { + self.data().text + } } impl fmt::Debug for GreenToken { diff --git a/src/syntax/token.rs b/src/syntax/token.rs index fb68fe4..4d6077d 100644 --- a/src/syntax/token.rs +++ b/src/syntax/token.rs @@ -176,6 +176,20 @@ impl SyntaxToken { self.green().text(resolver) } + /// Returns `true` if `self` and `other` represent equal source text. + /// + /// This method is different from the `PartialEq` and `Eq` implementations in that it compares + /// the text and not the token position. + /// It is more efficient than comparing the result of + /// [`resolve_text`](SyntaxToken::resolve_text) because it compares the tokens' interned string + /// keys. + /// Therefore, it also does not require a [`Resolver`]. + /// **Note** that the result of the comparison may be wrong when comparing two tokens from + /// different trees that use different interners. + pub fn text_eq(&self, other: &Self) -> bool { + self.green().text_key() == other.green().text_key() + } + /// Returns the unterlying green tree token of this token. pub fn green(&self) -> &GreenToken { self.parent diff --git a/tests/it/basic.rs b/tests/it/basic.rs index c8102fe..c33e9ee 100644 --- a/tests/it/basic.rs +++ b/tests/it/basic.rs @@ -18,6 +18,15 @@ fn two_level_tree() -> Element<'static> { ]) } +fn tree_with_eq_tokens() -> Element<'static> { + use Element::*; + Node(vec![ + Node(vec![Token("a"), Token("b")]), + Node(vec![Token("c")]), + Node(vec![Token("a"), Token("b"), Token("c")]), + ]) +} + #[test] fn create() { let tree = two_level_tree(); @@ -41,6 +50,35 @@ fn create() { } } +#[test] +fn token_text_eq() { + let tree = tree_with_eq_tokens(); + let (tree, _) = build_tree::<()>(&tree); + assert_eq!(tree.kind(), SyntaxKind(0)); + + let leaf0_0 = tree.children().next().unwrap().children_with_tokens().next().unwrap(); + let leaf0_0 = leaf0_0.into_token().unwrap(); + let leaf0_1 = tree.children().next().unwrap().children_with_tokens().nth(1).unwrap(); + let leaf0_1 = leaf0_1.into_token().unwrap(); + + let leaf1_0 = tree.children().nth(1).unwrap().children_with_tokens().next().unwrap(); + let leaf1_0 = leaf1_0.into_token().unwrap(); + + let leaf2_0 = tree.children().nth(2).unwrap().children_with_tokens().next().unwrap(); + let leaf2_0 = leaf2_0.into_token().unwrap(); + let leaf2_1 = tree.children().nth(2).unwrap().children_with_tokens().nth(1).unwrap(); + let leaf2_1 = leaf2_1.into_token().unwrap(); + let leaf2_2 = tree.children().nth(2).unwrap().children_with_tokens().nth(2).unwrap(); + let leaf2_2 = leaf2_2.into_token().unwrap(); + + assert!(leaf0_0.text_eq(leaf2_0)); + assert!(leaf0_1.text_eq(leaf2_1)); + assert!(leaf1_0.text_eq(leaf2_2)); + assert!(!leaf0_0.text_eq(leaf0_1)); + assert!(!leaf2_1.text_eq(leaf2_2)); + assert!(!leaf1_0.text_eq(leaf2_0)); +} + #[test] fn data() { let tree = two_level_tree();