aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax
diff options
context:
space:
mode:
authorDawer <[email protected]>2021-05-06 06:07:06 +0100
committerDawer <[email protected]>2021-05-06 06:07:06 +0100
commitd7e169fe55a15dd684e7a93dd111c66ed49ed949 (patch)
tree5ae79079f66e095caebf1f39f5fad1be9de197dc /crates/syntax
parentdc4fa504ea2723bd5083284cabf81b4c5806ed4b (diff)
Borrow text from nodes of immutable syntax trees
Diffstat (limited to 'crates/syntax')
-rw-r--r--crates/syntax/src/ast/node_ext.rs36
-rw-r--r--crates/syntax/src/token_text.rs38
2 files changed, 49 insertions, 25 deletions
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 492fbc4a0..8e6d7b092 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -1,10 +1,11 @@
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, NodeOrToken};
8 9
9use crate::{ 10use crate::{
10 ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode}, 11 ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode},
@@ -12,19 +13,19 @@ use crate::{
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,28 @@ impl ast::NameRef {
33 } 34 }
34} 35}
35 36
36fn text_of_first_token(node: &SyntaxNode) -> TokenText { 37fn _text_of_first_token(node: &SyntaxNode) -> Cow<'_, str> {
37 let first_token = 38 fn cow_map<F: FnOnce(&GreenNodeData) -> &str>(green: Cow<GreenNodeData>, f: F) -> Cow<str> {
38 node.green().children().next().and_then(|it| it.into_token()).unwrap().to_owned(); 39 match green {
40 Cow::Borrowed(green_ref) => Cow::Borrowed(f(green_ref)),
41 Cow::Owned(green) => Cow::Owned(f(&green).to_owned()),
42 }
43 }
44
45 cow_map(node.green(), |green_ref| {
46 green_ref.children().next().and_then(NodeOrToken::into_token).unwrap().text()
47 })
48}
39 49
40 TokenText(first_token) 50fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
51 fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
52 green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
53 }
54
55 match node.green() {
56 Cow::Borrowed(green_ref) => TokenText::Borrowed(first_token(green_ref).text()),
57 Cow::Owned(green) => TokenText::Owned(first_token(&green).to_owned()),
58 }
41} 59}
42 60
43#[derive(Debug, PartialEq, Eq, Clone)] 61#[derive(Debug, PartialEq, Eq, Clone)]
@@ -412,7 +430,7 @@ impl fmt::Display for NameOrNameRef {
412} 430}
413 431
414impl NameOrNameRef { 432impl NameOrNameRef {
415 pub fn text(&self) -> TokenText { 433 pub fn text(&self) -> TokenText<'_> {
416 match self { 434 match self {
417 NameOrNameRef::Name(name) => name.text(), 435 NameOrNameRef::Name(name) => name.text(),
418 NameOrNameRef::NameRef(name_ref) => name_ref.text(), 436 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..e29f4eea4 100644
--- a/crates/syntax/src/token_text.rs
+++ b/crates/syntax/src/token_text.rs
@@ -2,75 +2,81 @@
2 2
3use std::{cmp::Ordering, fmt, ops}; 3use std::{cmp::Ordering, fmt, ops};
4 4
5pub struct TokenText(pub(crate) rowan::GreenToken); 5pub enum TokenText<'a> {
6 Borrowed(&'a str),
7 Owned(rowan::GreenToken),
8}
6 9
7impl TokenText { 10impl TokenText<'_> {
8 pub fn as_str(&self) -> &str { 11 pub fn as_str(&self) -> &str {
9 self.0.text() 12 match self {
13 TokenText::Borrowed(it) => *it,
14 TokenText::Owned(green) => green.text(),
15 }
10 } 16 }
11} 17}
12 18
13impl ops::Deref for TokenText { 19impl ops::Deref for TokenText<'_> {
14 type Target = str; 20 type Target = str;
15 21
16 fn deref(&self) -> &str { 22 fn deref(&self) -> &str {
17 self.as_str() 23 self.as_str()
18 } 24 }
19} 25}
20impl AsRef<str> for TokenText { 26impl AsRef<str> for TokenText<'_> {
21 fn as_ref(&self) -> &str { 27 fn as_ref(&self) -> &str {
22 self.as_str() 28 self.as_str()
23 } 29 }
24} 30}
25 31
26impl From<TokenText> for String { 32impl From<TokenText<'_>> for String {
27 fn from(token_text: TokenText) -> Self { 33 fn from(token_text: TokenText) -> Self {
28 token_text.as_str().into() 34 token_text.as_str().into()
29 } 35 }
30} 36}
31 37
32impl PartialEq<&'_ str> for TokenText { 38impl PartialEq<&'_ str> for TokenText<'_> {
33 fn eq(&self, other: &&str) -> bool { 39 fn eq(&self, other: &&str) -> bool {
34 self.as_str() == *other 40 self.as_str() == *other
35 } 41 }
36} 42}
37impl PartialEq<TokenText> for &'_ str { 43impl PartialEq<TokenText<'_>> for &'_ str {
38 fn eq(&self, other: &TokenText) -> bool { 44 fn eq(&self, other: &TokenText) -> bool {
39 other == self 45 other == self
40 } 46 }
41} 47}
42impl PartialEq<String> for TokenText { 48impl PartialEq<String> for TokenText<'_> {
43 fn eq(&self, other: &String) -> bool { 49 fn eq(&self, other: &String) -> bool {
44 self.as_str() == other.as_str() 50 self.as_str() == other.as_str()
45 } 51 }
46} 52}
47impl PartialEq<TokenText> for String { 53impl PartialEq<TokenText<'_>> for String {
48 fn eq(&self, other: &TokenText) -> bool { 54 fn eq(&self, other: &TokenText) -> bool {
49 other == self 55 other == self
50 } 56 }
51} 57}
52impl PartialEq for TokenText { 58impl PartialEq for TokenText<'_> {
53 fn eq(&self, other: &TokenText) -> bool { 59 fn eq(&self, other: &TokenText) -> bool {
54 self.as_str() == other.as_str() 60 self.as_str() == other.as_str()
55 } 61 }
56} 62}
57impl Eq for TokenText {} 63impl Eq for TokenText<'_> {}
58impl Ord for TokenText { 64impl Ord for TokenText<'_> {
59 fn cmp(&self, other: &Self) -> Ordering { 65 fn cmp(&self, other: &Self) -> Ordering {
60 self.as_str().cmp(other.as_str()) 66 self.as_str().cmp(other.as_str())
61 } 67 }
62} 68}
63impl PartialOrd for TokenText { 69impl PartialOrd for TokenText<'_> {
64 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 70 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
65 Some(self.cmp(other)) 71 Some(self.cmp(other))
66 } 72 }
67} 73}
68impl fmt::Display for TokenText { 74impl fmt::Display for TokenText<'_> {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 fmt::Display::fmt(self.as_str(), f) 76 fmt::Display::fmt(self.as_str(), f)
71 } 77 }
72} 78}
73impl fmt::Debug for TokenText { 79impl fmt::Debug for TokenText<'_> {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 fmt::Debug::fmt(self.as_str(), f) 81 fmt::Debug::fmt(self.as_str(), f)
76 } 82 }