aboutsummaryrefslogtreecommitdiff
path: root/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast')
-rw-r--r--src/ast/generated.rs54
-rw-r--r--src/ast/generated.rs.tera22
-rw-r--r--src/ast/mod.rs70
3 files changed, 146 insertions, 0 deletions
diff --git a/src/ast/generated.rs b/src/ast/generated.rs
new file mode 100644
index 000000000..612b04f86
--- /dev/null
+++ b/src/ast/generated.rs
@@ -0,0 +1,54 @@
1use std::sync::Arc;
2use {
3 SyntaxNode, SyntaxRoot, TreeRoot, AstNode,
4 SyntaxKind::*,
5};
6
7
8#[derive(Debug)]
9pub struct File<R: TreeRoot = Arc<SyntaxRoot>> {
10 syntax: SyntaxNode<R>,
11}
12
13impl<R: TreeRoot> AstNode<R> for File<R> {
14 fn cast(syntax: SyntaxNode<R>) -> Option<Self> {
15 match syntax.kind() {
16 FILE => Some(File { syntax }),
17 _ => None,
18 }
19 }
20 fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
21}
22
23
24#[derive(Debug)]
25pub struct FnItem<R: TreeRoot = Arc<SyntaxRoot>> {
26 syntax: SyntaxNode<R>,
27}
28
29impl<R: TreeRoot> AstNode<R> for FnItem<R> {
30 fn cast(syntax: SyntaxNode<R>) -> Option<Self> {
31 match syntax.kind() {
32 FN_ITEM => Some(FnItem { syntax }),
33 _ => None,
34 }
35 }
36 fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
37}
38
39
40#[derive(Debug)]
41pub struct Name<R: TreeRoot = Arc<SyntaxRoot>> {
42 syntax: SyntaxNode<R>,
43}
44
45impl<R: TreeRoot> AstNode<R> for Name<R> {
46 fn cast(syntax: SyntaxNode<R>) -> Option<Self> {
47 match syntax.kind() {
48 NAME => Some(Name { syntax }),
49 _ => None,
50 }
51 }
52 fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
53}
54
diff --git a/src/ast/generated.rs.tera b/src/ast/generated.rs.tera
new file mode 100644
index 000000000..f2559383a
--- /dev/null
+++ b/src/ast/generated.rs.tera
@@ -0,0 +1,22 @@
1use std::sync::Arc;
2use {
3 SyntaxNode, SyntaxRoot, TreeRoot, AstNode,
4 SyntaxKind::*,
5};
6{% for node in ast %}
7{% set Name = node.kind | camel %}
8#[derive(Debug)]
9pub struct {{ Name }}<R: TreeRoot = Arc<SyntaxRoot>> {
10 syntax: SyntaxNode<R>,
11}
12
13impl<R: TreeRoot> AstNode<R> for {{ Name }}<R> {
14 fn cast(syntax: SyntaxNode<R>) -> Option<Self> {
15 match syntax.kind() {
16 {{ node.kind }} => Some({{ Name }} { syntax }),
17 _ => None,
18 }
19 }
20 fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
21}
22{% endfor %}
diff --git a/src/ast/mod.rs b/src/ast/mod.rs
new file mode 100644
index 000000000..dc7e006c9
--- /dev/null
+++ b/src/ast/mod.rs
@@ -0,0 +1,70 @@
1mod generated;
2
3use std::sync::Arc;
4use {
5 SyntaxNode, SyntaxRoot, TreeRoot,
6 SyntaxKind::*,
7};
8pub use self::generated::*;
9
10pub trait AstNode<R: TreeRoot>: Sized {
11 fn cast(syntax: SyntaxNode<R>) -> Option<Self>;
12 fn syntax(&self) -> &SyntaxNode<R>;
13}
14
15impl File<Arc<SyntaxRoot>> {
16 pub fn parse(text: &str) -> Self {
17 File::cast(::parse(text)).unwrap()
18 }
19}
20
21impl<R: TreeRoot> File<R> {
22 pub fn functions<'a>(&'a self) -> impl Iterator<Item = FnItem<R>> + 'a {
23 self.syntax()
24 .children()
25 .filter_map(FnItem::cast)
26 }
27}
28
29impl<R: TreeRoot> FnItem<R> {
30 pub fn name(&self) -> Option<Name<R>> {
31 self.syntax()
32 .children()
33 .filter_map(Name::cast)
34 .next()
35 }
36
37 pub fn has_atom_attr(&self, atom: &str) -> bool {
38 self.syntax()
39 .children()
40 .filter(|node| node.kind() == ATTR)
41 .any(|attr| {
42 let mut metas = attr.children().filter(|node| node.kind() == META_ITEM);
43 let meta = match metas.next() {
44 None => return false,
45 Some(meta) => {
46 if metas.next().is_some() {
47 return false;
48 }
49 meta
50 }
51 };
52 let mut children = meta.children();
53 match children.next() {
54 None => false,
55 Some(child) => {
56 if children.next().is_some() {
57 return false;
58 }
59 child.kind() == IDENT && child.text() == atom
60 }
61 }
62 })
63 }
64}
65
66impl<R: TreeRoot> Name<R> {
67 pub fn text(&self) -> String {
68 self.syntax().text()
69 }
70}