diff options
Diffstat (limited to 'crates/ra_assists/src/ast_editor.rs')
-rw-r--r-- | crates/ra_assists/src/ast_editor.rs | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs index 95b871b30..5b6952426 100644 --- a/crates/ra_assists/src/ast_editor.rs +++ b/crates/ra_assists/src/ast_editor.rs | |||
@@ -1,6 +1,8 @@ | |||
1 | use std::{iter, ops::RangeInclusive}; | 1 | use std::{iter, ops::RangeInclusive}; |
2 | 2 | ||
3 | use arrayvec::ArrayVec; | 3 | use arrayvec::ArrayVec; |
4 | use itertools::Itertools; | ||
5 | |||
4 | use hir::Name; | 6 | use hir::Name; |
5 | use ra_fmt::leading_indent; | 7 | use ra_fmt::leading_indent; |
6 | use ra_syntax::{ | 8 | use ra_syntax::{ |
@@ -168,8 +170,7 @@ impl AstEditor<ast::NamedFieldList> { | |||
168 | 170 | ||
169 | impl AstEditor<ast::ItemList> { | 171 | impl AstEditor<ast::ItemList> { |
170 | pub fn append_items(&mut self, items: impl Iterator<Item = ast::ImplItem>) { | 172 | pub fn append_items(&mut self, items: impl Iterator<Item = ast::ImplItem>) { |
171 | let n_existing_items = self.ast().impl_items().count(); | 173 | if !self.ast().syntax().text().contains_char('\n') { |
172 | if n_existing_items == 0 { | ||
173 | self.do_make_multiline(); | 174 | self.do_make_multiline(); |
174 | } | 175 | } |
175 | items.for_each(|it| self.append_item(it)); | 176 | items.for_each(|it| self.append_item(it)); |
@@ -288,6 +289,94 @@ impl AstBuilder<ast::NameRef> { | |||
288 | } | 289 | } |
289 | } | 290 | } |
290 | 291 | ||
292 | impl AstBuilder<ast::Path> { | ||
293 | fn from_text(text: &str) -> ast::Path { | ||
294 | ast_node_from_file_text(text) | ||
295 | } | ||
296 | |||
297 | pub fn from_pieces(enum_name: ast::Name, var_name: ast::Name) -> ast::Path { | ||
298 | Self::from_text(&format!("{}::{}", enum_name.syntax(), var_name.syntax())) | ||
299 | } | ||
300 | } | ||
301 | |||
302 | impl AstBuilder<ast::BindPat> { | ||
303 | fn from_text(text: &str) -> ast::BindPat { | ||
304 | ast_node_from_file_text(&format!("fn f({}: ())", text)) | ||
305 | } | ||
306 | |||
307 | pub fn from_name(name: &ast::Name) -> ast::BindPat { | ||
308 | Self::from_text(name.text()) | ||
309 | } | ||
310 | } | ||
311 | |||
312 | impl AstBuilder<ast::PlaceholderPat> { | ||
313 | fn from_text(text: &str) -> ast::PlaceholderPat { | ||
314 | ast_node_from_file_text(&format!("fn f({}: ())", text)) | ||
315 | } | ||
316 | |||
317 | pub fn placeholder() -> ast::PlaceholderPat { | ||
318 | Self::from_text("_") | ||
319 | } | ||
320 | } | ||
321 | |||
322 | impl AstBuilder<ast::TupleStructPat> { | ||
323 | fn from_text(text: &str) -> ast::TupleStructPat { | ||
324 | ast_node_from_file_text(&format!("fn f({}: ())", text)) | ||
325 | } | ||
326 | |||
327 | pub fn from_pieces( | ||
328 | path: &ast::Path, | ||
329 | pats: impl Iterator<Item = ast::Pat>, | ||
330 | ) -> ast::TupleStructPat { | ||
331 | let pats_str = pats.map(|p| p.syntax().to_string()).collect::<Vec<_>>().join(", "); | ||
332 | Self::from_text(&format!("{}({})", path.syntax(), pats_str)) | ||
333 | } | ||
334 | } | ||
335 | |||
336 | impl AstBuilder<ast::StructPat> { | ||
337 | fn from_text(text: &str) -> ast::StructPat { | ||
338 | ast_node_from_file_text(&format!("fn f({}: ())", text)) | ||
339 | } | ||
340 | |||
341 | pub fn from_pieces(path: &ast::Path, pats: impl Iterator<Item = ast::Pat>) -> ast::StructPat { | ||
342 | let pats_str = pats.map(|p| p.syntax().to_string()).collect::<Vec<_>>().join(", "); | ||
343 | Self::from_text(&format!("{}{{ {} }}", path.syntax(), pats_str)) | ||
344 | } | ||
345 | } | ||
346 | |||
347 | impl AstBuilder<ast::PathPat> { | ||
348 | fn from_text(text: &str) -> ast::PathPat { | ||
349 | ast_node_from_file_text(&format!("fn f({}: ())", text)) | ||
350 | } | ||
351 | |||
352 | pub fn from_path(path: &ast::Path) -> ast::PathPat { | ||
353 | let path_str = path.syntax().text().to_string(); | ||
354 | Self::from_text(path_str.as_str()) | ||
355 | } | ||
356 | } | ||
357 | |||
358 | impl AstBuilder<ast::MatchArm> { | ||
359 | fn from_text(text: &str) -> ast::MatchArm { | ||
360 | ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text)) | ||
361 | } | ||
362 | |||
363 | pub fn from_pieces(pats: impl Iterator<Item = ast::Pat>, expr: &ast::Expr) -> ast::MatchArm { | ||
364 | let pats_str = pats.map(|p| p.syntax().to_string()).join(" | "); | ||
365 | Self::from_text(&format!("{} => {}", pats_str, expr.syntax())) | ||
366 | } | ||
367 | } | ||
368 | |||
369 | impl AstBuilder<ast::MatchArmList> { | ||
370 | fn from_text(text: &str) -> ast::MatchArmList { | ||
371 | ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text)) | ||
372 | } | ||
373 | |||
374 | pub fn from_arms(arms: impl Iterator<Item = ast::MatchArm>) -> ast::MatchArmList { | ||
375 | let arms_str = arms.map(|arm| format!("\n {}", arm.syntax())).join(","); | ||
376 | Self::from_text(&format!("{},\n", arms_str)) | ||
377 | } | ||
378 | } | ||
379 | |||
291 | fn ast_node_from_file_text<N: AstNode>(text: &str) -> N { | 380 | fn ast_node_from_file_text<N: AstNode>(text: &str) -> N { |
292 | let parse = SourceFile::parse(text); | 381 | let parse = SourceFile::parse(text); |
293 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap().to_owned(); | 382 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap().to_owned(); |