aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-04-02 08:23:18 +0100
committerAleksey Kladov <[email protected]>2019-04-02 08:23:29 +0100
commitae282d8da63a82077361bc142b2b9a272a2eac64 (patch)
treecdb7b23e4abf9623286fbf5ef34a0108c0b5f25e /crates/ra_syntax/src/ast.rs
parentf874d372bb7f756dfa6ebc22ca838657c8ff1539 (diff)
add ast::tokens
Diffstat (limited to 'crates/ra_syntax/src/ast.rs')
-rw-r--r--crates/ra_syntax/src/ast.rs106
1 files changed, 12 insertions, 94 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
2mod generated; 2mod generated;
3mod traits; 3mod traits;
4mod tokens;
4 5
5use std::marker::PhantomData; 6use std::marker::PhantomData;
6 7
@@ -15,6 +16,7 @@ use crate::{
15pub use self::{ 16pub 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
54pub 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
52impl Attr { 64impl 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)]
100pub struct Comment<'a>(SyntaxToken<'a>);
101
102impl<'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)]
142pub enum CommentFlavor {
143 Line,
144 Doc,
145 ModuleDoc,
146 Multiline,
147}
148
149impl 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
168pub struct Whitespace<'a>(SyntaxToken<'a>);
169
170impl<'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
193impl Name { 111impl 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();