diff --git a/Cargo.lock b/Cargo.lock index c411ce8e62..c378014f00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1319,9 +1319,9 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "rowan" -version = "0.13.0-pre.3" +version = "0.13.0-pre.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77d315d6f2e33f294412faa47f41b56bdb3fce72c999d384b5e78c8d21551b13" +checksum = "32a5fc82ed0b7e7fba157331f0d8f64abd73bced6e7ac2a4dfa0c4cf0ab584e8" dependencies = [ "countme", "hashbrown", diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 3e9abd8a19..d61f4b31a4 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs @@ -283,7 +283,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option { }; let loc = db.lookup_intern_macro(id); let arg = loc.kind.arg(db)?; - Some(arg.green()) + Some(arg.green().into()) } fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option> { diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index 556f808825..c0bc599188 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml @@ -13,7 +13,7 @@ doctest = false [dependencies] cov-mark = { version = "1.1", features = ["thread-local"] } itertools = "0.10.0" -rowan = "=0.13.0-pre.3" +rowan = "=0.13.0-pre.5" rustc_lexer = { version = "716.0.0", package = "rustc-ap-rustc_lexer" } rustc-hash = "1.1.0" arrayvec = "0.7" diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs index c9229c4e07..ba263be0db 100644 --- a/crates/syntax/src/algo.rs +++ b/crates/syntax/src/algo.rs @@ -555,7 +555,7 @@ impl SyntaxRewriter<'_> { fn element_to_green(element: SyntaxElement) -> NodeOrToken { match element { - NodeOrToken::Node(it) => NodeOrToken::Node(it.green()), + NodeOrToken::Node(it) => NodeOrToken::Node(it.green().into_owned()), NodeOrToken::Token(it) => NodeOrToken::Token(it.green().to_owned()), } } diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 42da096061..4bcea28cca 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -572,7 +572,7 @@ fn ast_from_text(text: &str) -> N { } fn unroot(n: SyntaxNode) -> SyntaxNode { - SyntaxNode::new_root(n.green()) + SyntaxNode::new_root(n.green().into()) } pub mod tokens { diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 492fbc4a0f..bef49238f5 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -1,30 +1,31 @@ //! Various extension methods to ast Nodes, which are hard to code-generate. //! Extensions for various expressions live in a sibling `expr_extensions` module. -use std::{fmt, iter::successors}; +use std::{borrow::Cow, fmt, iter::successors}; use itertools::Itertools; use parser::SyntaxKind; +use rowan::{GreenNodeData, GreenTokenData}; use crate::{ ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode}, - SmolStr, SyntaxElement, SyntaxToken, TokenText, T, + NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T, }; impl ast::Lifetime { - pub fn text(&self) -> TokenText { + pub fn text(&self) -> TokenText<'_> { text_of_first_token(self.syntax()) } } impl ast::Name { - pub fn text(&self) -> TokenText { + pub fn text(&self) -> TokenText<'_> { text_of_first_token(self.syntax()) } } impl ast::NameRef { - pub fn text(&self) -> TokenText { + pub fn text(&self) -> TokenText<'_> { text_of_first_token(self.syntax()) } @@ -33,11 +34,15 @@ impl ast::NameRef { } } -fn text_of_first_token(node: &SyntaxNode) -> TokenText { - let first_token = - node.green().children().next().and_then(|it| it.into_token()).unwrap().to_owned(); +fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> { + fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData { + green_ref.children().next().and_then(NodeOrToken::into_token).unwrap() + } - TokenText(first_token) + match node.green() { + Cow::Borrowed(green_ref) => TokenText::borrowed(first_token(green_ref).text()), + Cow::Owned(green) => TokenText::owned(first_token(&green).to_owned()), + } } #[derive(Debug, PartialEq, Eq, Clone)] @@ -412,7 +417,7 @@ impl fmt::Display for NameOrNameRef { } impl NameOrNameRef { - pub fn text(&self) -> TokenText { + 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/token_text.rs b/crates/syntax/src/token_text.rs index d2ed0a12a4..f3e8b321a7 100644 --- a/crates/syntax/src/token_text.rs +++ b/crates/syntax/src/token_text.rs @@ -2,75 +2,93 @@ use std::{cmp::Ordering, fmt, ops}; -pub struct TokenText(pub(crate) rowan::GreenToken); +use rowan::GreenToken; + +pub struct TokenText<'a>(pub(crate) Repr<'a>); + +pub(crate) enum Repr<'a> { + Borrowed(&'a str), + Owned(GreenToken), +} + +impl<'a> TokenText<'a> { + pub(crate) fn borrowed(text: &'a str) -> Self { + TokenText(Repr::Borrowed(text)) + } + + pub(crate) fn owned(green: GreenToken) -> Self { + TokenText(Repr::Owned(green)) + } -impl TokenText { pub fn as_str(&self) -> &str { - self.0.text() + match self.0 { + Repr::Borrowed(it) => it, + Repr::Owned(ref green) => green.text(), + } } } -impl ops::Deref for TokenText { +impl ops::Deref for TokenText<'_> { type Target = str; fn deref(&self) -> &str { self.as_str() } } -impl AsRef for TokenText { +impl AsRef for TokenText<'_> { fn as_ref(&self) -> &str { self.as_str() } } -impl From for String { +impl From> for String { fn from(token_text: TokenText) -> Self { token_text.as_str().into() } } -impl PartialEq<&'_ str> for TokenText { +impl PartialEq<&'_ str> for TokenText<'_> { fn eq(&self, other: &&str) -> bool { self.as_str() == *other } } -impl PartialEq for &'_ str { +impl PartialEq> for &'_ str { fn eq(&self, other: &TokenText) -> bool { other == self } } -impl PartialEq for TokenText { +impl PartialEq for TokenText<'_> { fn eq(&self, other: &String) -> bool { self.as_str() == other.as_str() } } -impl PartialEq for String { +impl PartialEq> for String { fn eq(&self, other: &TokenText) -> bool { other == self } } -impl PartialEq for TokenText { +impl PartialEq for TokenText<'_> { fn eq(&self, other: &TokenText) -> bool { self.as_str() == other.as_str() } } -impl Eq for TokenText {} -impl Ord for TokenText { +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 { +impl PartialOrd for TokenText<'_> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl fmt::Display for TokenText { +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 { +impl fmt::Debug for TokenText<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(self.as_str(), f) }