diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 6d7db5fb26c..2772d736444 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -8,23 +8,23 @@ use crate::{ ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode}, - SmolStr, SyntaxElement, SyntaxToken, T, + SmolStr, SyntaxElement, SyntaxToken, TokenText, T, }; impl ast::Lifetime { - pub fn text(&self) -> SmolStr { + pub fn text(&self) -> TokenText { text_of_first_token(self.syntax()) } } impl ast::Name { - pub fn text(&self) -> SmolStr { + pub fn text(&self) -> TokenText { text_of_first_token(self.syntax()) } } impl ast::NameRef { - pub fn text(&self) -> SmolStr { + pub fn text(&self) -> TokenText { text_of_first_token(self.syntax()) } @@ -33,8 +33,11 @@ pub fn as_tuple_field(&self) -> Option { } } -fn text_of_first_token(node: &SyntaxNode) -> SmolStr { - node.green().children().next().and_then(|it| it.into_token()).unwrap().text().into() +fn text_of_first_token(node: &SyntaxNode) -> TokenText { + let first_token = + node.green().children().next().and_then(|it| it.into_token()).unwrap().to_owned(); + + TokenText(first_token) } pub enum Macro { @@ -376,7 +379,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } impl NameOrNameRef { - pub fn text(&self) -> SmolStr { + pub fn text(&self) -> TokenText { match self { NameOrNameRef::Name(name) => name.text(), NameOrNameRef::NameRef(name_ref) => name_ref.text(), diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 2a5c61171b3..90de6bef6f6 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -29,6 +29,7 @@ macro_rules! eprintln { mod parsing; mod validation; mod ptr; +mod token_text; #[cfg(test)] mod tests; @@ -55,6 +56,7 @@ macro_rules! eprintln { SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, SyntaxToken, SyntaxTreeBuilder, }, + token_text::TokenText, }; pub use parser::{SyntaxKind, T}; pub use rowan::{ diff --git a/crates/syntax/src/token_text.rs b/crates/syntax/src/token_text.rs new file mode 100644 index 00000000000..d2ed0a12a46 --- /dev/null +++ b/crates/syntax/src/token_text.rs @@ -0,0 +1,77 @@ +//! Yet another version of owned string, backed by a syntax tree token. + +use std::{cmp::Ordering, fmt, ops}; + +pub struct TokenText(pub(crate) rowan::GreenToken); + +impl TokenText { + pub fn as_str(&self) -> &str { + self.0.text() + } +} + +impl ops::Deref for TokenText { + type Target = str; + + fn deref(&self) -> &str { + self.as_str() + } +} +impl AsRef for TokenText { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl From for String { + fn from(token_text: TokenText) -> Self { + token_text.as_str().into() + } +} + +impl PartialEq<&'_ str> for TokenText { + fn eq(&self, other: &&str) -> bool { + self.as_str() == *other + } +} +impl PartialEq for &'_ str { + fn eq(&self, other: &TokenText) -> bool { + other == self + } +} +impl PartialEq for TokenText { + fn eq(&self, other: &String) -> bool { + self.as_str() == other.as_str() + } +} +impl PartialEq for String { + fn eq(&self, other: &TokenText) -> bool { + other == self + } +} +impl PartialEq for TokenText { + fn eq(&self, other: &TokenText) -> bool { + self.as_str() == other.as_str() + } +} +impl Eq for TokenText {} +impl Ord for TokenText { + fn cmp(&self, other: &Self) -> Ordering { + self.as_str().cmp(other.as_str()) + } +} +impl PartialOrd for TokenText { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl fmt::Display for TokenText { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} +impl fmt::Debug for TokenText { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.as_str(), f) + } +}