diff options
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 135 |
2 files changed, 136 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index a2f862869..f464d6534 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -5,6 +5,7 @@ mod traits; | |||
5 | mod tokens; | 5 | mod tokens; |
6 | mod extensions; | 6 | mod extensions; |
7 | mod expr_extensions; | 7 | mod expr_extensions; |
8 | pub mod make; | ||
8 | 9 | ||
9 | use std::marker::PhantomData; | 10 | use std::marker::PhantomData; |
10 | 11 | ||
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs new file mode 100644 index 000000000..c06c62b3b --- /dev/null +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -0,0 +1,135 @@ | |||
1 | //! This module contains free-standing functions for creating AST fragments out | ||
2 | //! of smaller pieces. | ||
3 | use itertools::Itertools; | ||
4 | |||
5 | use crate::{ast, AstNode, SourceFile}; | ||
6 | |||
7 | pub fn name_ref(text: &str) -> ast::NameRef { | ||
8 | ast_from_text(&format!("fn f() {{ {}; }}", text)) | ||
9 | } | ||
10 | |||
11 | pub fn path_from_name_ref(name_ref: ast::NameRef) -> ast::Path { | ||
12 | path_from_text(&name_ref.syntax().to_string()) | ||
13 | } | ||
14 | pub fn path_qualified(qual: ast::Path, name_ref: ast::NameRef) -> ast::Path { | ||
15 | path_from_text(&format!("{}::{}", qual.syntax(), name_ref.syntax())) | ||
16 | } | ||
17 | fn path_from_text(text: &str) -> ast::Path { | ||
18 | ast_from_text(text) | ||
19 | } | ||
20 | |||
21 | pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordField { | ||
22 | return match expr { | ||
23 | Some(expr) => from_text(&format!("{}: {}", name.syntax(), expr.syntax())), | ||
24 | None => from_text(&name.syntax().to_string()), | ||
25 | }; | ||
26 | |||
27 | fn from_text(text: &str) -> ast::RecordField { | ||
28 | ast_from_text(&format!("fn f() {{ S {{ {}, }} }}", text)) | ||
29 | } | ||
30 | } | ||
31 | |||
32 | pub fn block_from_expr(e: ast::Expr) -> ast::Block { | ||
33 | return from_text(&format!("{{ {} }}", e.syntax())); | ||
34 | |||
35 | fn from_text(text: &str) -> ast::Block { | ||
36 | ast_from_text(&format!("fn f() {}", text)) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | pub fn expr_unit() -> ast::Expr { | ||
41 | expr_from_text("()") | ||
42 | } | ||
43 | pub fn expr_unimplemented() -> ast::Expr { | ||
44 | expr_from_text("unimplemented!()") | ||
45 | } | ||
46 | fn expr_from_text(text: &str) -> ast::Expr { | ||
47 | ast_from_text(&format!("const C: () = {};", text)) | ||
48 | } | ||
49 | |||
50 | pub fn bind_pat(name: ast::Name) -> ast::BindPat { | ||
51 | return from_text(name.text()); | ||
52 | |||
53 | fn from_text(text: &str) -> ast::BindPat { | ||
54 | ast_from_text(&format!("fn f({}: ())", text)) | ||
55 | } | ||
56 | } | ||
57 | |||
58 | pub fn placeholder_pat() -> ast::PlaceholderPat { | ||
59 | return from_text("_"); | ||
60 | |||
61 | fn from_text(text: &str) -> ast::PlaceholderPat { | ||
62 | ast_from_text(&format!("fn f({}: ())", text)) | ||
63 | } | ||
64 | } | ||
65 | |||
66 | pub fn tuple_struct_pat( | ||
67 | path: ast::Path, | ||
68 | pats: impl Iterator<Item = ast::Pat>, | ||
69 | ) -> ast::TupleStructPat { | ||
70 | let pats_str = pats.map(|p| p.syntax().to_string()).join(", "); | ||
71 | return from_text(&format!("{}({})", path.syntax(), pats_str)); | ||
72 | |||
73 | fn from_text(text: &str) -> ast::TupleStructPat { | ||
74 | ast_from_text(&format!("fn f({}: ())", text)) | ||
75 | } | ||
76 | } | ||
77 | |||
78 | pub fn record_pat(path: ast::Path, pats: impl Iterator<Item = ast::Pat>) -> ast::RecordPat { | ||
79 | let pats_str = pats.map(|p| p.syntax().to_string()).join(", "); | ||
80 | return from_text(&format!("{}{{ {} }}", path.syntax(), pats_str)); | ||
81 | |||
82 | fn from_text(text: &str) -> ast::RecordPat { | ||
83 | ast_from_text(&format!("fn f({}: ())", text)) | ||
84 | } | ||
85 | } | ||
86 | |||
87 | pub fn path_pat(path: ast::Path) -> ast::PathPat { | ||
88 | let path_str = path.syntax().text().to_string(); | ||
89 | return from_text(path_str.as_str()); | ||
90 | fn from_text(text: &str) -> ast::PathPat { | ||
91 | ast_from_text(&format!("fn f({}: ())", text)) | ||
92 | } | ||
93 | } | ||
94 | |||
95 | pub fn match_arm(pats: impl Iterator<Item = ast::Pat>, expr: ast::Expr) -> ast::MatchArm { | ||
96 | let pats_str = pats.map(|p| p.syntax().to_string()).join(" | "); | ||
97 | return from_text(&format!("{} => {}", pats_str, expr.syntax())); | ||
98 | |||
99 | fn from_text(text: &str) -> ast::MatchArm { | ||
100 | ast_from_text(&format!("fn f() {{ match () {{{}}} }}", text)) | ||
101 | } | ||
102 | } | ||
103 | |||
104 | pub fn match_arm_list(arms: impl Iterator<Item = ast::MatchArm>) -> ast::MatchArmList { | ||
105 | let arms_str = arms.map(|arm| format!("\n {}", arm.syntax())).join(","); | ||
106 | return from_text(&format!("{},\n", arms_str)); | ||
107 | |||
108 | fn from_text(text: &str) -> ast::MatchArmList { | ||
109 | ast_from_text(&format!("fn f() {{ match () {{{}}} }}", text)) | ||
110 | } | ||
111 | } | ||
112 | |||
113 | pub fn where_pred(path: ast::Path, bounds: impl Iterator<Item = ast::TypeBound>) -> ast::WherePred { | ||
114 | let bounds = bounds.map(|b| b.syntax().to_string()).join(" + "); | ||
115 | return from_text(&format!("{}: {}", path.syntax(), bounds)); | ||
116 | |||
117 | fn from_text(text: &str) -> ast::WherePred { | ||
118 | ast_from_text(&format!("fn f() where {} {{ }}", text)) | ||
119 | } | ||
120 | } | ||
121 | |||
122 | pub fn where_clause(preds: impl Iterator<Item = ast::WherePred>) -> ast::WhereClause { | ||
123 | let preds = preds.map(|p| p.syntax().to_string()).join(", "); | ||
124 | return from_text(preds.as_str()); | ||
125 | |||
126 | fn from_text(text: &str) -> ast::WhereClause { | ||
127 | ast_from_text(&format!("fn f() where {} {{ }}", text)) | ||
128 | } | ||
129 | } | ||
130 | |||
131 | fn ast_from_text<N: AstNode>(text: &str) -> N { | ||
132 | let parse = SourceFile::parse(text); | ||
133 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); | ||
134 | res | ||
135 | } | ||