diff options
Diffstat (limited to 'crates/ra_syntax/src/yellow/mod.rs')
-rw-r--r-- | crates/ra_syntax/src/yellow/mod.rs | 174 |
1 files changed, 108 insertions, 66 deletions
diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow/mod.rs index 0596e702f..c621b1d6a 100644 --- a/crates/ra_syntax/src/yellow/mod.rs +++ b/crates/ra_syntax/src/yellow/mod.rs | |||
@@ -1,100 +1,142 @@ | |||
1 | mod builder; | 1 | mod builder; |
2 | mod green; | ||
3 | mod red; | ||
4 | mod syntax; | ||
5 | mod syntax_text; | 2 | mod syntax_text; |
6 | 3 | ||
7 | use std::{ | 4 | use std::{ |
8 | sync::Arc, | 5 | fmt, |
9 | ptr, | 6 | hash::{Hash, Hasher}, |
10 | }; | ||
11 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError, SyntaxNodeChildren}; | ||
12 | pub(crate) use self::{ | ||
13 | builder::GreenBuilder, | ||
14 | green::GreenNode, | ||
15 | red::RedNode, | ||
16 | syntax_text::SyntaxText, | ||
17 | }; | 7 | }; |
8 | use rowan::Types; | ||
9 | use {SyntaxKind, TextUnit, TextRange, SmolStr}; | ||
10 | use self::syntax_text::SyntaxText; | ||
18 | 11 | ||
19 | #[derive(Debug)] | 12 | pub use rowan::{TreeRoot}; |
20 | pub struct SyntaxRoot { | 13 | pub(crate) use self::builder::GreenBuilder; |
21 | red: RedNode, | 14 | |
22 | pub(crate) errors: Vec<SyntaxError>, | 15 | #[derive(Debug, Clone, Copy)] |
16 | pub enum RaTypes {} | ||
17 | impl Types for RaTypes { | ||
18 | type Kind = SyntaxKind; | ||
19 | type RootData = Vec<SyntaxError>; | ||
23 | } | 20 | } |
24 | 21 | ||
25 | pub trait TreeRoot: Clone + Send + Sync { | 22 | pub type OwnedRoot = ::rowan::OwnedRoot<RaTypes>; |
26 | fn borrowed(&self) -> RefRoot; | 23 | pub type RefRoot<'a> = ::rowan::RefRoot<'a, RaTypes>; |
27 | fn owned(&self) -> OwnedRoot; | 24 | |
25 | pub type GreenNode = ::rowan::GreenNode<RaTypes>; | ||
28 | 26 | ||
29 | #[doc(hidden)] | 27 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
30 | fn syntax_root(&self) -> &SyntaxRoot; | 28 | pub struct SyntaxError { |
29 | pub msg: String, | ||
30 | pub offset: TextUnit, | ||
31 | } | 31 | } |
32 | #[derive(Clone, Debug)] | ||
33 | pub struct OwnedRoot(Arc<SyntaxRoot>); | ||
34 | #[derive(Clone, Copy, Debug)] | ||
35 | pub struct RefRoot<'a>(&'a OwnedRoot); // TODO: shared_from_this instead of double indirection | ||
36 | 32 | ||
37 | impl<'a> RefRoot<'a> { | 33 | #[derive(Clone, Copy)] |
38 | fn syntax_root(&self) -> &'a SyntaxRoot { | 34 | pub struct SyntaxNode<R: TreeRoot<RaTypes> = OwnedRoot>( |
39 | self.0.syntax_root() | 35 | ::rowan::SyntaxNode<RaTypes, R>, |
36 | ); | ||
37 | pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>; | ||
38 | |||
39 | impl<R1, R2> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> | ||
40 | where | ||
41 | R1: TreeRoot<RaTypes>, | ||
42 | R2: TreeRoot<RaTypes>, | ||
43 | { | ||
44 | fn eq(&self, other: &SyntaxNode<R1>) -> bool { | ||
45 | self.0 == other.0 | ||
40 | } | 46 | } |
41 | } | 47 | } |
42 | 48 | ||
43 | impl TreeRoot for OwnedRoot { | 49 | impl<R: TreeRoot<RaTypes>> Eq for SyntaxNode<R> {} |
44 | fn borrowed(&self) -> RefRoot { | 50 | impl<R: TreeRoot<RaTypes>> Hash for SyntaxNode<R> { |
45 | RefRoot(&self) | 51 | fn hash<H: Hasher>(&self, state: &mut H) { |
46 | } | 52 | self.0.hash(state) |
47 | fn owned(&self) -> OwnedRoot { | ||
48 | self.clone() | ||
49 | } | 53 | } |
54 | } | ||
50 | 55 | ||
51 | fn syntax_root(&self) -> &SyntaxRoot { | 56 | impl SyntaxNode<OwnedRoot> { |
52 | &*self.0 | 57 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxNode { |
58 | SyntaxNode(::rowan::SyntaxNode::new(green, errors)) | ||
59 | } | ||
60 | } | ||
61 | impl<'a> SyntaxNode<RefRoot<'a>> { | ||
62 | pub fn leaf_text(self) -> Option<&'a SmolStr> { | ||
63 | self.0.leaf_text() | ||
53 | } | 64 | } |
54 | } | 65 | } |
55 | 66 | ||
56 | impl<'a> TreeRoot for RefRoot<'a> { | 67 | impl<R: TreeRoot<RaTypes>> SyntaxNode<R> { |
57 | fn borrowed(&self) -> RefRoot { | 68 | pub(crate) fn root_data(&self) -> &Vec<SyntaxError> { |
58 | *self | 69 | self.0.root_data() |
70 | } | ||
71 | pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { | ||
72 | self.0.replace_with(replacement) | ||
73 | } | ||
74 | pub fn borrowed<'a>(&'a self) -> SyntaxNode<RefRoot<'a>> { | ||
75 | SyntaxNode(self.0.borrowed()) | ||
76 | } | ||
77 | pub fn owned(&self) -> SyntaxNode<OwnedRoot> { | ||
78 | SyntaxNode(self.0.owned()) | ||
79 | } | ||
80 | pub fn kind(&self) -> SyntaxKind { | ||
81 | self.0.kind() | ||
59 | } | 82 | } |
60 | fn owned(&self) -> OwnedRoot { | 83 | pub fn range(&self) -> TextRange { |
61 | self.0.clone() | 84 | self.0.range() |
62 | } | 85 | } |
63 | fn syntax_root(&self) -> &SyntaxRoot { | 86 | pub fn text(&self) -> SyntaxText { |
64 | self.0.syntax_root() | 87 | SyntaxText::new(self.borrowed()) |
88 | } | ||
89 | pub fn is_leaf(&self) -> bool { | ||
90 | self.0.is_leaf() | ||
91 | } | ||
92 | pub fn parent(&self) -> Option<SyntaxNode<R>> { | ||
93 | self.0.parent().map(SyntaxNode) | ||
94 | } | ||
95 | pub fn first_child(&self) -> Option<SyntaxNode<R>> { | ||
96 | self.0.first_child().map(SyntaxNode) | ||
97 | } | ||
98 | pub fn last_child(&self) -> Option<SyntaxNode<R>> { | ||
99 | self.0.last_child().map(SyntaxNode) | ||
100 | } | ||
101 | pub fn next_sibling(&self) -> Option<SyntaxNode<R>> { | ||
102 | self.0.next_sibling().map(SyntaxNode) | ||
103 | } | ||
104 | pub fn prev_sibling(&self) -> Option<SyntaxNode<R>> { | ||
105 | self.0.prev_sibling().map(SyntaxNode) | ||
106 | } | ||
107 | pub fn children(&self) -> SyntaxNodeChildren<R> { | ||
108 | SyntaxNodeChildren(self.0.children()) | ||
65 | } | 109 | } |
66 | } | 110 | } |
67 | 111 | ||
68 | impl SyntaxRoot { | 112 | impl<R: TreeRoot<RaTypes>> fmt::Debug for SyntaxNode<R> { |
69 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot { | 113 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
70 | SyntaxRoot { | 114 | write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; |
71 | red: RedNode::new_root(green), | 115 | if has_short_text(self.kind()) { |
72 | errors, | 116 | write!(fmt, " \"{}\"", self.text())?; |
73 | } | 117 | } |
118 | Ok(()) | ||
74 | } | 119 | } |
75 | } | 120 | } |
76 | 121 | ||
77 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | 122 | #[derive(Debug)] |
78 | pub(crate) struct RedPtr(ptr::NonNull<RedNode>); | 123 | pub struct SyntaxNodeChildren<R: TreeRoot<RaTypes>>( |
79 | 124 | ::rowan::SyntaxNodeChildren<RaTypes, R> | |
80 | unsafe impl Send for RedPtr {} | 125 | ); |
81 | |||
82 | unsafe impl Sync for RedPtr {} | ||
83 | 126 | ||
84 | impl RedPtr { | 127 | impl<R: TreeRoot<RaTypes>> Iterator for SyntaxNodeChildren<R> { |
85 | fn new(red: &RedNode) -> RedPtr { | 128 | type Item = SyntaxNode<R>; |
86 | RedPtr(red.into()) | ||
87 | } | ||
88 | 129 | ||
89 | unsafe fn get<'a>(self, _root: &'a SyntaxRoot) -> &'a RedNode { | 130 | fn next(&mut self) -> Option<SyntaxNode<R>> { |
90 | &*self.0.as_ptr() | 131 | self.0.next().map(SyntaxNode) |
91 | } | 132 | } |
92 | } | 133 | } |
93 | 134 | ||
94 | #[test] | 135 | |
95 | fn assert_send_sync() { | 136 | fn has_short_text(kind: SyntaxKind) -> bool { |
96 | fn f<T: Send + Sync>() {} | 137 | use SyntaxKind::*; |
97 | f::<GreenNode>(); | 138 | match kind { |
98 | f::<RedNode>(); | 139 | IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, |
99 | f::<SyntaxNode>(); | 140 | _ => false, |
141 | } | ||
100 | } | 142 | } |