aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-06 23:19:52 +0100
committerGitHub <[email protected]>2021-05-06 23:19:52 +0100
commit0ee945e289c438e87d4701401059e8c407710e7b (patch)
tree6b16e28da049a1f627b26eda1a2595a6b3cd84cd
parent6fccb152b4646877e38dc29dce1b0cd826eb6908 (diff)
parent90a5dca0a2dbb858ee34eb7de06de8a1cad9e488 (diff)
Merge #8280
8280: Borrow text of immutable syntax node r=iDawer a=iDawer In https://github.com/rust-analyzer/rowan/pull/101 `rowan::SyntaxNode::green` returns `Cow<'_, GreenNodeData>`. It returns borrow of green node of immutable syntax tree node. Using this we can return borrowed text from `ast::Name::text`. ~~However now it allocates in case of mutable syntax trees.~~ (see next comment) The idea comes from https://github.com/rust-analyzer/rowan/pull/100#issuecomment-809330325 Co-authored-by: Dawer <[email protected]>
-rw-r--r--Cargo.lock4
-rw-r--r--crates/hir_expand/src/db.rs2
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/algo.rs2
-rw-r--r--crates/syntax/src/ast/make.rs2
-rw-r--r--crates/syntax/src/ast/node_ext.rs25
-rw-r--r--crates/syntax/src/token_text.rs50
7 files changed, 55 insertions, 32 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c411ce8e6..c378014f0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1319,9 +1319,9 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
1319 1319
1320[[package]] 1320[[package]]
1321name = "rowan" 1321name = "rowan"
1322version = "0.13.0-pre.3" 1322version = "0.13.0-pre.5"
1323source = "registry+https://github.com/rust-lang/crates.io-index" 1323source = "registry+https://github.com/rust-lang/crates.io-index"
1324checksum = "77d315d6f2e33f294412faa47f41b56bdb3fce72c999d384b5e78c8d21551b13" 1324checksum = "32a5fc82ed0b7e7fba157331f0d8f64abd73bced6e7ac2a4dfa0c4cf0ab584e8"
1325dependencies = [ 1325dependencies = [
1326 "countme", 1326 "countme",
1327 "hashbrown", 1327 "hashbrown",
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 3e9abd8a1..d61f4b31a 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<GreenNode> {
283 }; 283 };
284 let loc = db.lookup_intern_macro(id); 284 let loc = db.lookup_intern_macro(id);
285 let arg = loc.kind.arg(db)?; 285 let arg = loc.kind.arg(db)?;
286 Some(arg.green()) 286 Some(arg.green().into())
287} 287}
288 288
289fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<TokenExpander>> { 289fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<TokenExpander>> {
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 556f80882..c0bc59918 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
13[dependencies] 13[dependencies]
14cov-mark = { version = "1.1", features = ["thread-local"] } 14cov-mark = { version = "1.1", features = ["thread-local"] }
15itertools = "0.10.0" 15itertools = "0.10.0"
16rowan = "=0.13.0-pre.3" 16rowan = "=0.13.0-pre.5"
17rustc_lexer = { version = "716.0.0", package = "rustc-ap-rustc_lexer" } 17rustc_lexer = { version = "716.0.0", package = "rustc-ap-rustc_lexer" }
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19arrayvec = "0.7" 19arrayvec = "0.7"
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
index c9229c4e0..ba263be0d 100644
--- a/crates/syntax/src/algo.rs
+++ b/crates/syntax/src/algo.rs
@@ -555,7 +555,7 @@ impl SyntaxRewriter<'_> {
555 555
556fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> { 556fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
557 match element { 557 match element {
558 NodeOrToken::Node(it) => NodeOrToken::Node(it.green()), 558 NodeOrToken::Node(it) => NodeOrToken::Node(it.green().into_owned()),
559 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().to_owned()), 559 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().to_owned()),
560 } 560 }
561} 561}
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 42da09606..4bcea28cc 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -572,7 +572,7 @@ fn ast_from_text<N: AstNode>(text: &str) -> N {
572} 572}
573 573
574fn unroot(n: SyntaxNode) -> SyntaxNode { 574fn unroot(n: SyntaxNode) -> SyntaxNode {
575 SyntaxNode::new_root(n.green()) 575 SyntaxNode::new_root(n.green().into())
576} 576}
577 577
578pub mod tokens { 578pub mod tokens {
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 492fbc4a0..bef49238f 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -1,30 +1,31 @@
1//! Various extension methods to ast Nodes, which are hard to code-generate. 1//! Various extension methods to ast Nodes, which are hard to code-generate.
2//! Extensions for various expressions live in a sibling `expr_extensions` module. 2//! Extensions for various expressions live in a sibling `expr_extensions` module.
3 3
4use std::{fmt, iter::successors}; 4use std::{borrow::Cow, fmt, iter::successors};
5 5
6use itertools::Itertools; 6use itertools::Itertools;
7use parser::SyntaxKind; 7use parser::SyntaxKind;
8use rowan::{GreenNodeData, GreenTokenData};
8 9
9use crate::{ 10use crate::{
10 ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode}, 11 ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode},
11 SmolStr, SyntaxElement, SyntaxToken, TokenText, T, 12 NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T,
12}; 13};
13 14
14impl ast::Lifetime { 15impl ast::Lifetime {
15 pub fn text(&self) -> TokenText { 16 pub fn text(&self) -> TokenText<'_> {
16 text_of_first_token(self.syntax()) 17 text_of_first_token(self.syntax())
17 } 18 }
18} 19}
19 20
20impl ast::Name { 21impl ast::Name {
21 pub fn text(&self) -> TokenText { 22 pub fn text(&self) -> TokenText<'_> {
22 text_of_first_token(self.syntax()) 23 text_of_first_token(self.syntax())
23 } 24 }
24} 25}
25 26
26impl ast::NameRef { 27impl ast::NameRef {
27 pub fn text(&self) -> TokenText { 28 pub fn text(&self) -> TokenText<'_> {
28 text_of_first_token(self.syntax()) 29 text_of_first_token(self.syntax())
29 } 30 }
30 31
@@ -33,11 +34,15 @@ impl ast::NameRef {
33 } 34 }
34} 35}
35 36
36fn text_of_first_token(node: &SyntaxNode) -> TokenText { 37fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
37 let first_token = 38 fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
38 node.green().children().next().and_then(|it| it.into_token()).unwrap().to_owned(); 39 green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
40 }
39 41
40 TokenText(first_token) 42 match node.green() {
43 Cow::Borrowed(green_ref) => TokenText::borrowed(first_token(green_ref).text()),
44 Cow::Owned(green) => TokenText::owned(first_token(&green).to_owned()),
45 }
41} 46}
42 47
43#[derive(Debug, PartialEq, Eq, Clone)] 48#[derive(Debug, PartialEq, Eq, Clone)]
@@ -412,7 +417,7 @@ impl fmt::Display for NameOrNameRef {
412} 417}
413 418
414impl NameOrNameRef { 419impl NameOrNameRef {
415 pub fn text(&self) -> TokenText { 420 pub fn text(&self) -> TokenText<'_> {
416 match self { 421 match self {
417 NameOrNameRef::Name(name) => name.text(), 422 NameOrNameRef::Name(name) => name.text(),
418 NameOrNameRef::NameRef(name_ref) => name_ref.text(), 423 NameOrNameRef::NameRef(name_ref) => name_ref.text(),
diff --git a/crates/syntax/src/token_text.rs b/crates/syntax/src/token_text.rs
index d2ed0a12a..f3e8b321a 100644
--- a/crates/syntax/src/token_text.rs
+++ b/crates/syntax/src/token_text.rs
@@ -2,75 +2,93 @@
2 2
3use std::{cmp::Ordering, fmt, ops}; 3use std::{cmp::Ordering, fmt, ops};
4 4
5pub struct TokenText(pub(crate) rowan::GreenToken); 5use rowan::GreenToken;
6
7pub struct TokenText<'a>(pub(crate) Repr<'a>);
8
9pub(crate) enum Repr<'a> {
10 Borrowed(&'a str),
11 Owned(GreenToken),
12}
13
14impl<'a> TokenText<'a> {
15 pub(crate) fn borrowed(text: &'a str) -> Self {
16 TokenText(Repr::Borrowed(text))
17 }
18
19 pub(crate) fn owned(green: GreenToken) -> Self {
20 TokenText(Repr::Owned(green))
21 }
6 22
7impl TokenText {
8 pub fn as_str(&self) -> &str { 23 pub fn as_str(&self) -> &str {
9 self.0.text() 24 match self.0 {
25 Repr::Borrowed(it) => it,
26 Repr::Owned(ref green) => green.text(),
27 }
10 } 28 }
11} 29}
12 30
13impl ops::Deref for TokenText { 31impl ops::Deref for TokenText<'_> {
14 type Target = str; 32 type Target = str;
15 33
16 fn deref(&self) -> &str { 34 fn deref(&self) -> &str {
17 self.as_str() 35 self.as_str()
18 } 36 }
19} 37}
20impl AsRef<str> for TokenText { 38impl AsRef<str> for TokenText<'_> {
21 fn as_ref(&self) -> &str { 39 fn as_ref(&self) -> &str {
22 self.as_str() 40 self.as_str()
23 } 41 }
24} 42}
25 43
26impl From<TokenText> for String { 44impl From<TokenText<'_>> for String {
27 fn from(token_text: TokenText) -> Self { 45 fn from(token_text: TokenText) -> Self {
28 token_text.as_str().into() 46 token_text.as_str().into()
29 } 47 }
30} 48}
31 49
32impl PartialEq<&'_ str> for TokenText { 50impl PartialEq<&'_ str> for TokenText<'_> {
33 fn eq(&self, other: &&str) -> bool { 51 fn eq(&self, other: &&str) -> bool {
34 self.as_str() == *other 52 self.as_str() == *other
35 } 53 }
36} 54}
37impl PartialEq<TokenText> for &'_ str { 55impl PartialEq<TokenText<'_>> for &'_ str {
38 fn eq(&self, other: &TokenText) -> bool { 56 fn eq(&self, other: &TokenText) -> bool {
39 other == self 57 other == self
40 } 58 }
41} 59}
42impl PartialEq<String> for TokenText { 60impl PartialEq<String> for TokenText<'_> {
43 fn eq(&self, other: &String) -> bool { 61 fn eq(&self, other: &String) -> bool {
44 self.as_str() == other.as_str() 62 self.as_str() == other.as_str()
45 } 63 }
46} 64}
47impl PartialEq<TokenText> for String { 65impl PartialEq<TokenText<'_>> for String {
48 fn eq(&self, other: &TokenText) -> bool { 66 fn eq(&self, other: &TokenText) -> bool {
49 other == self 67 other == self
50 } 68 }
51} 69}
52impl PartialEq for TokenText { 70impl PartialEq for TokenText<'_> {
53 fn eq(&self, other: &TokenText) -> bool { 71 fn eq(&self, other: &TokenText) -> bool {
54 self.as_str() == other.as_str() 72 self.as_str() == other.as_str()
55 } 73 }
56} 74}
57impl Eq for TokenText {} 75impl Eq for TokenText<'_> {}
58impl Ord for TokenText { 76impl Ord for TokenText<'_> {
59 fn cmp(&self, other: &Self) -> Ordering { 77 fn cmp(&self, other: &Self) -> Ordering {
60 self.as_str().cmp(other.as_str()) 78 self.as_str().cmp(other.as_str())
61 } 79 }
62} 80}
63impl PartialOrd for TokenText { 81impl PartialOrd for TokenText<'_> {
64 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 82 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
65 Some(self.cmp(other)) 83 Some(self.cmp(other))
66 } 84 }
67} 85}
68impl fmt::Display for TokenText { 86impl fmt::Display for TokenText<'_> {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 fmt::Display::fmt(self.as_str(), f) 88 fmt::Display::fmt(self.as_str(), f)
71 } 89 }
72} 90}
73impl fmt::Debug for TokenText { 91impl fmt::Debug for TokenText<'_> {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 fmt::Debug::fmt(self.as_str(), f) 93 fmt::Debug::fmt(self.as_str(), f)
76 } 94 }