diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-06 23:19:52 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-05-06 23:19:52 +0100 |
commit | 0ee945e289c438e87d4701401059e8c407710e7b (patch) | |
tree | 6b16e28da049a1f627b26eda1a2595a6b3cd84cd /crates/syntax | |
parent | 6fccb152b4646877e38dc29dce1b0cd826eb6908 (diff) | |
parent | 90a5dca0a2dbb858ee34eb7de06de8a1cad9e488 (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]>
Diffstat (limited to 'crates/syntax')
-rw-r--r-- | crates/syntax/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/syntax/src/algo.rs | 2 | ||||
-rw-r--r-- | crates/syntax/src/ast/make.rs | 2 | ||||
-rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 25 | ||||
-rw-r--r-- | crates/syntax/src/token_text.rs | 50 |
5 files changed, 52 insertions, 29 deletions
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] |
14 | cov-mark = { version = "1.1", features = ["thread-local"] } | 14 | cov-mark = { version = "1.1", features = ["thread-local"] } |
15 | itertools = "0.10.0" | 15 | itertools = "0.10.0" |
16 | rowan = "=0.13.0-pre.3" | 16 | rowan = "=0.13.0-pre.5" |
17 | rustc_lexer = { version = "716.0.0", package = "rustc-ap-rustc_lexer" } | 17 | rustc_lexer = { version = "716.0.0", package = "rustc-ap-rustc_lexer" } |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | arrayvec = "0.7" | 19 | arrayvec = "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 | ||
556 | fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> { | 556 | fn 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 | ||
574 | fn unroot(n: SyntaxNode) -> SyntaxNode { | 574 | fn unroot(n: SyntaxNode) -> SyntaxNode { |
575 | SyntaxNode::new_root(n.green()) | 575 | SyntaxNode::new_root(n.green().into()) |
576 | } | 576 | } |
577 | 577 | ||
578 | pub mod tokens { | 578 | pub 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 | ||
4 | use std::{fmt, iter::successors}; | 4 | use std::{borrow::Cow, fmt, iter::successors}; |
5 | 5 | ||
6 | use itertools::Itertools; | 6 | use itertools::Itertools; |
7 | use parser::SyntaxKind; | 7 | use parser::SyntaxKind; |
8 | use rowan::{GreenNodeData, GreenTokenData}; | ||
8 | 9 | ||
9 | use crate::{ | 10 | use 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 | ||
14 | impl ast::Lifetime { | 15 | impl 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 | ||
20 | impl ast::Name { | 21 | impl 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 | ||
26 | impl ast::NameRef { | 27 | impl 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 | ||
36 | fn text_of_first_token(node: &SyntaxNode) -> TokenText { | 37 | fn 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 | ||
414 | impl NameOrNameRef { | 419 | impl 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 | ||
3 | use std::{cmp::Ordering, fmt, ops}; | 3 | use std::{cmp::Ordering, fmt, ops}; |
4 | 4 | ||
5 | pub struct TokenText(pub(crate) rowan::GreenToken); | 5 | use rowan::GreenToken; |
6 | |||
7 | pub struct TokenText<'a>(pub(crate) Repr<'a>); | ||
8 | |||
9 | pub(crate) enum Repr<'a> { | ||
10 | Borrowed(&'a str), | ||
11 | Owned(GreenToken), | ||
12 | } | ||
13 | |||
14 | impl<'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 | ||
7 | impl 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 | ||
13 | impl ops::Deref for TokenText { | 31 | impl 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 | } |
20 | impl AsRef<str> for TokenText { | 38 | impl 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 | ||
26 | impl From<TokenText> for String { | 44 | impl 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 | ||
32 | impl PartialEq<&'_ str> for TokenText { | 50 | impl 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 | } |
37 | impl PartialEq<TokenText> for &'_ str { | 55 | impl 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 | } |
42 | impl PartialEq<String> for TokenText { | 60 | impl 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 | } |
47 | impl PartialEq<TokenText> for String { | 65 | impl 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 | } |
52 | impl PartialEq for TokenText { | 70 | impl 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 | } |
57 | impl Eq for TokenText {} | 75 | impl Eq for TokenText<'_> {} |
58 | impl Ord for TokenText { | 76 | impl 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 | } |
63 | impl PartialOrd for TokenText { | 81 | impl 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 | } |
68 | impl fmt::Display for TokenText { | 86 | impl 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 | } |
73 | impl fmt::Debug for TokenText { | 91 | impl 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 | } |