aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast
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
parentf874d372bb7f756dfa6ebc22ca838657c8ff1539 (diff)
add ast::tokens
Diffstat (limited to 'crates/ra_syntax/src/ast')
-rw-r--r--crates/ra_syntax/src/ast/tokens.rs93
-rw-r--r--crates/ra_syntax/src/ast/traits.rs2
2 files changed, 94 insertions, 1 deletions
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 @@
1use crate::{
2 SyntaxToken,
3 SyntaxKind::{COMMENT, WHITESPACE},
4 ast::AstToken,
5};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub struct Comment<'a>(SyntaxToken<'a>);
9
10impl<'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
23impl<'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)]
47pub enum CommentFlavor {
48 Line,
49 Doc,
50 ModuleDoc,
51 Multiline,
52}
53
54impl 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
73pub struct Whitespace<'a>(SyntaxToken<'a>);
74
75impl<'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
88impl<'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
3use crate::{ 3use 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
8pub trait TypeAscriptionOwner: AstNode { 8pub trait TypeAscriptionOwner: AstNode {