aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast/make.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/ast/make.rs')
-rw-r--r--crates/ra_syntax/src/ast/make.rs61
1 files changed, 47 insertions, 14 deletions
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index 36e648180..862eb1172 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -2,7 +2,7 @@
2//! of smaller pieces. 2//! of smaller pieces.
3use itertools::Itertools; 3use itertools::Itertools;
4 4
5use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxToken}; 5use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken};
6 6
7pub fn name(text: &str) -> ast::Name { 7pub fn name(text: &str) -> ast::Name {
8 ast_from_text(&format!("mod {};", text)) 8 ast_from_text(&format!("mod {};", text))
@@ -33,6 +33,21 @@ pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordF
33 } 33 }
34} 34}
35 35
36pub fn block_expr(
37 stmts: impl IntoIterator<Item = ast::Stmt>,
38 tail_expr: Option<ast::Expr>,
39) -> ast::BlockExpr {
40 let mut text = "{\n".to_string();
41 for stmt in stmts.into_iter() {
42 text += &format!(" {}\n", stmt.syntax());
43 }
44 if let Some(tail_expr) = tail_expr {
45 text += &format!(" {}\n", tail_expr.syntax())
46 }
47 text += "}";
48 ast_from_text(&format!("fn f() {}", text))
49}
50
36pub fn block_from_expr(e: ast::Expr) -> ast::Block { 51pub fn block_from_expr(e: ast::Expr) -> ast::Block {
37 return from_text(&format!("{{ {} }}", e.syntax())); 52 return from_text(&format!("{{ {} }}", e.syntax()));
38 53
@@ -62,6 +77,13 @@ pub fn expr_return() -> ast::Expr {
62pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr { 77pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr {
63 expr_from_text(&format!("match {} {}", expr.syntax(), match_arm_list.syntax())) 78 expr_from_text(&format!("match {} {}", expr.syntax(), match_arm_list.syntax()))
64} 79}
80pub fn expr_if(condition: ast::Expr, then_branch: ast::BlockExpr) -> ast::Expr {
81 expr_from_text(&format!("if {} {}", condition.syntax(), then_branch.syntax()))
82}
83pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr {
84 let token = token(op);
85 expr_from_text(&format!("{}{}", token, expr.syntax()))
86}
65fn expr_from_text(text: &str) -> ast::Expr { 87fn expr_from_text(text: &str) -> ast::Expr {
66 ast_from_text(&format!("const C: () = {};", text)) 88 ast_from_text(&format!("const C: () = {};", text))
67} 89}
@@ -122,11 +144,18 @@ pub fn match_arm(pats: impl IntoIterator<Item = ast::Pat>, expr: ast::Expr) -> a
122} 144}
123 145
124pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList { 146pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList {
125 let arms_str = arms.into_iter().map(|arm| format!("\n {}", arm.syntax())).join(","); 147 let arms_str = arms
126 return from_text(&format!("{},\n", arms_str)); 148 .into_iter()
149 .map(|arm| {
150 let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like());
151 let comma = if needs_comma { "," } else { "" };
152 format!(" {}{}\n", arm.syntax(), comma)
153 })
154 .collect::<String>();
155 return from_text(&format!("{}", arms_str));
127 156
128 fn from_text(text: &str) -> ast::MatchArmList { 157 fn from_text(text: &str) -> ast::MatchArmList {
129 ast_from_text(&format!("fn f() {{ match () {{{}}} }}", text)) 158 ast_from_text(&format!("fn f() {{ match () {{\n{}}} }}", text))
130 } 159 }
131} 160}
132 161
@@ -151,14 +180,6 @@ pub fn where_clause(preds: impl IntoIterator<Item = ast::WherePred>) -> ast::Whe
151 } 180 }
152} 181}
153 182
154pub fn if_expression(condition: &ast::Expr, statement: &str) -> ast::IfExpr {
155 ast_from_text(&format!(
156 "fn f() {{ if !{} {{\n {}\n}}\n}}",
157 condition.syntax().text(),
158 statement
159 ))
160}
161
162pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetStmt { 183pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetStmt {
163 let text = match initializer { 184 let text = match initializer {
164 Some(it) => format!("let {} = {};", pattern.syntax(), it.syntax()), 185 Some(it) => format!("let {} = {};", pattern.syntax(), it.syntax()),
@@ -166,6 +187,9 @@ pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetSt
166 }; 187 };
167 ast_from_text(&format!("fn f() {{ {} }}", text)) 188 ast_from_text(&format!("fn f() {{ {} }}", text))
168} 189}
190pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt {
191 ast_from_text(&format!("fn f() {{ {}; }}", expr.syntax()))
192}
169 193
170pub fn token(kind: SyntaxKind) -> SyntaxToken { 194pub fn token(kind: SyntaxKind) -> SyntaxToken {
171 tokens::SOURCE_FILE 195 tokens::SOURCE_FILE
@@ -179,7 +203,16 @@ pub fn token(kind: SyntaxKind) -> SyntaxToken {
179 203
180fn ast_from_text<N: AstNode>(text: &str) -> N { 204fn ast_from_text<N: AstNode>(text: &str) -> N {
181 let parse = SourceFile::parse(text); 205 let parse = SourceFile::parse(text);
182 parse.tree().syntax().descendants().find_map(N::cast).unwrap() 206 let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap();
207 let node = node.syntax().clone();
208 let node = unroot(node);
209 let node = N::cast(node).unwrap();
210 assert_eq!(node.syntax().text_range().start(), 0.into());
211 node
212}
213
214fn unroot(n: SyntaxNode) -> SyntaxNode {
215 SyntaxNode::new_root(n.green().clone())
183} 216}
184 217
185pub mod tokens { 218pub mod tokens {
@@ -187,7 +220,7 @@ pub mod tokens {
187 use once_cell::sync::Lazy; 220 use once_cell::sync::Lazy;
188 221
189 pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = 222 pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> =
190 Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2)\n;")); 223 Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2, !true)\n;"));
191 224
192 pub fn comma() -> SyntaxToken { 225 pub fn comma() -> SyntaxToken {
193 SOURCE_FILE 226 SOURCE_FILE