diff options
author | Aleksey Kladov <[email protected]> | 2019-04-02 08:23:18 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-04-02 08:23:29 +0100 |
commit | ae282d8da63a82077361bc142b2b9a272a2eac64 (patch) | |
tree | cdb7b23e4abf9623286fbf5ef34a0108c0b5f25e /crates/ra_syntax | |
parent | f874d372bb7f756dfa6ebc22ca838657c8ff1539 (diff) |
add ast::tokens
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 106 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/tokens.rs | 93 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/traits.rs | 2 |
3 files changed, 106 insertions, 95 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 9950ab12d..beef2c6e2 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s | 1 | //! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s |
2 | mod generated; | 2 | mod generated; |
3 | mod traits; | 3 | mod traits; |
4 | mod tokens; | ||
4 | 5 | ||
5 | use std::marker::PhantomData; | 6 | use std::marker::PhantomData; |
6 | 7 | ||
@@ -15,6 +16,7 @@ use crate::{ | |||
15 | pub use self::{ | 16 | pub use self::{ |
16 | generated::*, | 17 | generated::*, |
17 | traits::*, | 18 | traits::*, |
19 | tokens::*, | ||
18 | }; | 20 | }; |
19 | 21 | ||
20 | /// The main trait to go from untyped `SyntaxNode` to a typed ast. The | 22 | /// The main trait to go from untyped `SyntaxNode` to a typed ast. The |
@@ -49,6 +51,16 @@ impl<'a, N: AstNode + 'a> Iterator for AstChildren<'a, N> { | |||
49 | } | 51 | } |
50 | } | 52 | } |
51 | 53 | ||
54 | pub trait AstToken<'a> { | ||
55 | fn cast(token: SyntaxToken<'a>) -> Option<Self> | ||
56 | where | ||
57 | Self: Sized; | ||
58 | fn syntax(&self) -> SyntaxToken<'a>; | ||
59 | fn text(&self) -> &'a SmolStr { | ||
60 | self.syntax().text() | ||
61 | } | ||
62 | } | ||
63 | |||
52 | impl Attr { | 64 | impl Attr { |
53 | pub fn is_inner(&self) -> bool { | 65 | pub fn is_inner(&self) -> bool { |
54 | let tt = match self.value() { | 66 | let tt = match self.value() { |
@@ -96,100 +108,6 @@ impl Attr { | |||
96 | } | 108 | } |
97 | } | 109 | } |
98 | 110 | ||
99 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
100 | pub struct Comment<'a>(SyntaxToken<'a>); | ||
101 | |||
102 | impl<'a> Comment<'a> { | ||
103 | pub fn cast(token: SyntaxToken<'a>) -> Option<Self> { | ||
104 | if token.kind() == COMMENT { | ||
105 | Some(Comment(token)) | ||
106 | } else { | ||
107 | None | ||
108 | } | ||
109 | } | ||
110 | |||
111 | pub fn syntax(&self) -> SyntaxToken<'a> { | ||
112 | self.0 | ||
113 | } | ||
114 | |||
115 | pub fn text(&self) -> &'a SmolStr { | ||
116 | self.0.text() | ||
117 | } | ||
118 | |||
119 | pub fn flavor(&self) -> CommentFlavor { | ||
120 | let text = self.text(); | ||
121 | if text.starts_with("///") { | ||
122 | CommentFlavor::Doc | ||
123 | } else if text.starts_with("//!") { | ||
124 | CommentFlavor::ModuleDoc | ||
125 | } else if text.starts_with("//") { | ||
126 | CommentFlavor::Line | ||
127 | } else { | ||
128 | CommentFlavor::Multiline | ||
129 | } | ||
130 | } | ||
131 | |||
132 | pub fn is_doc_comment(&self) -> bool { | ||
133 | self.flavor().is_doc_comment() | ||
134 | } | ||
135 | |||
136 | pub fn prefix(&self) -> &'static str { | ||
137 | self.flavor().prefix() | ||
138 | } | ||
139 | } | ||
140 | |||
141 | #[derive(Debug, PartialEq, Eq)] | ||
142 | pub enum CommentFlavor { | ||
143 | Line, | ||
144 | Doc, | ||
145 | ModuleDoc, | ||
146 | Multiline, | ||
147 | } | ||
148 | |||
149 | impl CommentFlavor { | ||
150 | pub fn prefix(&self) -> &'static str { | ||
151 | use self::CommentFlavor::*; | ||
152 | match *self { | ||
153 | Line => "//", | ||
154 | Doc => "///", | ||
155 | ModuleDoc => "//!", | ||
156 | Multiline => "/*", | ||
157 | } | ||
158 | } | ||
159 | |||
160 | pub fn is_doc_comment(&self) -> bool { | ||
161 | match self { | ||
162 | CommentFlavor::Doc | CommentFlavor::ModuleDoc => true, | ||
163 | _ => false, | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | pub struct Whitespace<'a>(SyntaxToken<'a>); | ||
169 | |||
170 | impl<'a> Whitespace<'a> { | ||
171 | pub fn cast(token: SyntaxToken<'a>) -> Option<Self> { | ||
172 | if token.kind() == WHITESPACE { | ||
173 | Some(Whitespace(token)) | ||
174 | } else { | ||
175 | None | ||
176 | } | ||
177 | } | ||
178 | |||
179 | pub fn syntax(&self) -> SyntaxToken<'a> { | ||
180 | self.0 | ||
181 | } | ||
182 | |||
183 | pub fn text(&self) -> &'a SmolStr { | ||
184 | self.0.text() | ||
185 | } | ||
186 | |||
187 | pub fn spans_multiple_lines(&self) -> bool { | ||
188 | let text = self.text(); | ||
189 | text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n')) | ||
190 | } | ||
191 | } | ||
192 | |||
193 | impl Name { | 111 | impl Name { |
194 | pub fn text(&self) -> &SmolStr { | 112 | pub fn text(&self) -> &SmolStr { |
195 | let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap(); | 113 | let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap(); |
diff --git a/crates/ra_syntax/src/ast/tokens.rs b/crates/ra_syntax/src/ast/tokens.rs new file mode 100644 index 000000000..c830cdccf --- /dev/null +++ b/crates/ra_syntax/src/ast/tokens.rs | |||
@@ -0,0 +1,93 @@ | |||
1 | use crate::{ | ||
2 | SyntaxToken, | ||
3 | SyntaxKind::{COMMENT, WHITESPACE}, | ||
4 | ast::AstToken, | ||
5 | }; | ||
6 | |||
7 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
8 | pub struct Comment<'a>(SyntaxToken<'a>); | ||
9 | |||
10 | impl<'a> AstToken<'a> for Comment<'a> { | ||
11 | fn cast(token: SyntaxToken<'a>) -> Option<Self> { | ||
12 | if token.kind() == COMMENT { | ||
13 | Some(Comment(token)) | ||
14 | } else { | ||
15 | None | ||
16 | } | ||
17 | } | ||
18 | fn syntax(&self) -> SyntaxToken<'a> { | ||
19 | self.0 | ||
20 | } | ||
21 | } | ||
22 | |||
23 | impl<'a> Comment<'a> { | ||
24 | pub fn flavor(&self) -> CommentFlavor { | ||
25 | let text = self.text(); | ||
26 | if text.starts_with("///") { | ||
27 | CommentFlavor::Doc | ||
28 | } else if text.starts_with("//!") { | ||
29 | CommentFlavor::ModuleDoc | ||
30 | } else if text.starts_with("//") { | ||
31 | CommentFlavor::Line | ||
32 | } else { | ||
33 | CommentFlavor::Multiline | ||
34 | } | ||
35 | } | ||
36 | |||
37 | pub fn is_doc_comment(&self) -> bool { | ||
38 | self.flavor().is_doc_comment() | ||
39 | } | ||
40 | |||
41 | pub fn prefix(&self) -> &'static str { | ||
42 | self.flavor().prefix() | ||
43 | } | ||
44 | } | ||
45 | |||
46 | #[derive(Debug, PartialEq, Eq)] | ||
47 | pub enum CommentFlavor { | ||
48 | Line, | ||
49 | Doc, | ||
50 | ModuleDoc, | ||
51 | Multiline, | ||
52 | } | ||
53 | |||
54 | impl CommentFlavor { | ||
55 | pub fn prefix(&self) -> &'static str { | ||
56 | use self::CommentFlavor::*; | ||
57 | match *self { | ||
58 | Line => "//", | ||
59 | Doc => "///", | ||
60 | ModuleDoc => "//!", | ||
61 | Multiline => "/*", | ||
62 | } | ||
63 | } | ||
64 | |||
65 | pub fn is_doc_comment(&self) -> bool { | ||
66 | match self { | ||
67 | CommentFlavor::Doc | CommentFlavor::ModuleDoc => true, | ||
68 | _ => false, | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | pub struct Whitespace<'a>(SyntaxToken<'a>); | ||
74 | |||
75 | impl<'a> AstToken<'a> for Whitespace<'a> { | ||
76 | fn cast(token: SyntaxToken<'a>) -> Option<Self> { | ||
77 | if token.kind() == WHITESPACE { | ||
78 | Some(Whitespace(token)) | ||
79 | } else { | ||
80 | None | ||
81 | } | ||
82 | } | ||
83 | fn syntax(&self) -> SyntaxToken<'a> { | ||
84 | self.0 | ||
85 | } | ||
86 | } | ||
87 | |||
88 | impl<'a> Whitespace<'a> { | ||
89 | pub fn spans_multiple_lines(&self) -> bool { | ||
90 | let text = self.text(); | ||
91 | text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n')) | ||
92 | } | ||
93 | } | ||
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index 85fe6d5e1..f9021d7bf 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs | |||
@@ -2,7 +2,7 @@ use itertools::Itertools; | |||
2 | 2 | ||
3 | use crate::{ | 3 | use crate::{ |
4 | syntax_node::{SyntaxNodeChildren, SyntaxElementChildren}, | 4 | syntax_node::{SyntaxNodeChildren, SyntaxElementChildren}, |
5 | ast::{self, child_opt, children, AstNode, AstChildren}, | 5 | ast::{self, child_opt, children, AstNode, AstToken, AstChildren}, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | pub trait TypeAscriptionOwner: AstNode { | 8 | pub trait TypeAscriptionOwner: AstNode { |