From c8f5792a365414e0233d72b34ee33c849c0b9ed6 Mon Sep 17 00:00:00 2001 From: Daiki Ihara Date: Tue, 8 Dec 2020 01:17:13 +0900 Subject: Add handling file_system_edit in test assists --- crates/assists/src/assist_context.rs | 14 +++++++-- crates/assists/src/tests.rs | 60 ++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 15 deletions(-) (limited to 'crates/assists') diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs index 69499ea32..cd22cf17d 100644 --- a/crates/assists/src/assist_context.rs +++ b/crates/assists/src/assist_context.rs @@ -4,10 +4,10 @@ use std::mem; use algo::find_covering_element; use hir::Semantics; -use ide_db::base_db::{FileId, FileRange}; +use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange}; use ide_db::{ label::Label, - source_change::{SourceChange, SourceFileEdit}, + source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, RootDatabase, }; use syntax::{ @@ -209,6 +209,7 @@ pub(crate) struct AssistBuilder { file_id: FileId, is_snippet: bool, source_file_edits: Vec, + file_system_edits: Vec, } impl AssistBuilder { @@ -218,6 +219,7 @@ impl AssistBuilder { file_id, is_snippet: false, source_file_edits: Vec::default(), + file_system_edits: Vec::default(), } } @@ -282,12 +284,18 @@ impl AssistBuilder { algo::diff(&node, &new).into_text_edit(&mut self.edit); } } + pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into) { + let file_system_edit = FileSystemEdit::CreateFile { dst: dst.clone() }; + self.file_system_edits.push(file_system_edit); + self.edit_file(dst.anchor); + self.insert(TextSize::from(0), content) + } fn finish(mut self) -> SourceChange { self.commit(); SourceChange { source_file_edits: mem::take(&mut self.source_file_edits), - file_system_edits: Default::default(), + file_system_edits: mem::take(&mut self.file_system_edits), is_snippet: self.is_snippet, } } diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs index 709a34d03..9002040ce 100644 --- a/crates/assists/src/tests.rs +++ b/crates/assists/src/tests.rs @@ -2,6 +2,7 @@ mod generated; use hir::Semantics; use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; +use ide_db::source_change::FileSystemEdit; use ide_db::RootDatabase; use syntax::TextRange; use test_utils::{assert_eq_text, extract_offset, extract_range}; @@ -47,7 +48,7 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) { let before = db.file_text(file_id).to_string(); let frange = FileRange { file_id, range: selection.into() }; - let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange) + let assist = Assist::resolved(&db, &AssistConfig::default(), frange) .into_iter() .find(|assist| assist.assist.id.0 == assist_id) .unwrap_or_else(|| { @@ -63,9 +64,12 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) { }); let actual = { - let change = assist.source_change.source_file_edits.pop().unwrap(); let mut actual = before; - change.edit.apply(&mut actual); + for source_file_edit in assist.source_change.source_file_edits { + if source_file_edit.file_id == file_id { + source_file_edit.edit.apply(&mut actual) + } + } actual }; assert_eq_text!(&after, &actual); @@ -99,20 +103,52 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: (Some(assist), ExpectedResult::After(after)) => { let mut source_change = assist.source_change; assert!(!source_change.source_file_edits.is_empty()); - let skip_header = source_change.source_file_edits.len() == 1; + let skip_header = source_change.source_file_edits.len() == 1 + && source_change.file_system_edits.len() == 0; source_change.source_file_edits.sort_by_key(|it| it.file_id); + let mut created_file_ids = Vec::new(); let mut buf = String::new(); + for file_system_edit in source_change.file_system_edits.clone() { + match file_system_edit { + FileSystemEdit::CreateFile { dst } => { + created_file_ids.push(dst.anchor); + } + _ => (), + } + } + for source_file_edit in source_change.source_file_edits { - let mut text = db.file_text(source_file_edit.file_id).as_ref().to_owned(); - source_file_edit.edit.apply(&mut text); - if !skip_header { - let sr = db.file_source_root(source_file_edit.file_id); - let sr = db.source_root(sr); - let path = sr.path_for_file(&source_file_edit.file_id).unwrap(); - format_to!(buf, "//- {}\n", path) + if created_file_ids.contains(&source_file_edit.file_id) { + let target_dst = source_change + .file_system_edits + .iter() + .find_map(|f| match f { + FileSystemEdit::CreateFile { dst } => { + if dst.anchor == source_file_edit.file_id { + Some(&dst.path) + } else { + None + } + } + _ => None, + }) + .unwrap(); + format_to!(buf, "//- {}\n", target_dst); + let mut text = String::new(); + source_file_edit.edit.apply(&mut text); + buf.push_str(&text); + } else { + let mut text = db.file_text(source_file_edit.file_id).as_ref().to_owned(); + source_file_edit.edit.apply(&mut text); + if !skip_header { + let sr = db.file_source_root(source_file_edit.file_id); + let sr = db.source_root(sr); + let path = sr.path_for_file(&source_file_edit.file_id).unwrap(); + format_to!(buf, "//- {}\n", path) + } + buf.push_str(&text); } - buf.push_str(&text); } assert_eq_text!(after, &buf); -- cgit v1.2.3 From 414576fb3059c8431f32a5bbe8fa117d4f3d83b7 Mon Sep 17 00:00:00 2001 From: Daiki Ihara Date: Tue, 8 Dec 2020 01:17:54 +0900 Subject: Add extract_module_to_file assist --- .../assists/src/handlers/extract_module_to_file.rs | 170 +++++++++++++++++++++ crates/assists/src/lib.rs | 2 + crates/assists/src/tests/generated.rs | 15 ++ 3 files changed, 187 insertions(+) create mode 100644 crates/assists/src/handlers/extract_module_to_file.rs (limited to 'crates/assists') diff --git a/crates/assists/src/handlers/extract_module_to_file.rs b/crates/assists/src/handlers/extract_module_to_file.rs new file mode 100644 index 000000000..5fc190fa6 --- /dev/null +++ b/crates/assists/src/handlers/extract_module_to_file.rs @@ -0,0 +1,170 @@ +use ast::edit::IndentLevel; +use ide_db::base_db::{AnchoredPathBuf, SourceDatabaseExt}; +use syntax::{ + ast::{self, edit::AstNodeEdit, NameOwner}, + AstNode, +}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: extract_module_to_file +// +// This assist extract module to file. +// +// ``` +// mod foo {<|> +// fn t() {} +// } +// ``` +// -> +// ``` +// mod foo; +// ``` +pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { + let assist_id = AssistId("extract_module_to_file", AssistKind::RefactorExtract); + let assist_label = "Extract module to file"; + let db = ctx.db(); + let module_ast = ctx.find_node_at_offset::()?; + let module_items = module_ast.item_list()?; + let dedent_module_items_text = module_items.dedent(IndentLevel(1)).to_string(); + let module_name = module_ast.name()?; + let target = module_ast.syntax().text_range(); + let anchor_file_id = ctx.frange.file_id; + let sr = db.file_source_root(anchor_file_id); + let sr = db.source_root(sr); + let file_path = sr.path_for_file(&anchor_file_id)?; + let (file_name, file_ext) = file_path.name_and_extension()?; + acc.add(assist_id, assist_label, target, |builder| { + builder.replace(target, format!("mod {};", module_name)); + let path = if is_main_or_lib(file_name) { + format!("./{}.{}", module_name, file_ext.unwrap()) + } else { + format!("./{}/{}.{}", file_name, module_name, file_ext.unwrap()) + }; + let dst = AnchoredPathBuf { anchor: anchor_file_id, path }; + let contents = update_module_items_string(dedent_module_items_text); + builder.create_file(dst, contents); + }) +} +fn is_main_or_lib(file_name: &str) -> bool { + file_name == "main".to_string() || file_name == "lib".to_string() +} +fn update_module_items_string(items_str: String) -> String { + let mut items_string_lines: Vec<&str> = items_str.lines().collect(); + items_string_lines.pop(); // Delete last line + items_string_lines.reverse(); + items_string_lines.pop(); // Delete first line + items_string_lines.reverse(); + + let string = items_string_lines.join("\n"); + format!("{}", string) +} + +#[cfg(test)] +mod tests { + use crate::tests::check_assist; + + use super::*; + + #[test] + fn extract_module_to_file_with_basic_module() { + check_assist( + extract_module_to_file, + r#" +//- /foo.rs crate:foo +mod tests {<|> + #[test] fn t() {} +} +"#, + r#" +//- /foo.rs +mod tests; +//- /foo/tests.rs +#[test] fn t() {}"#, + ) + } + + #[test] + fn extract_module_to_file_with_file_path() { + check_assist( + extract_module_to_file, + r#" +//- /src/foo.rs crate:foo +mod bar {<|> + fn f() { + + } +} +fn main() { + println!("Hello, world!"); +} +"#, + r#" +//- /src/foo.rs +mod bar; +fn main() { + println!("Hello, world!"); +} +//- /src/foo/bar.rs +fn f() { + +}"#, + ) + } + + #[test] + fn extract_module_to_file_with_main_filw() { + check_assist( + extract_module_to_file, + r#" +//- /main.rs +mod foo {<|> + fn f() { + + } +} +fn main() { + println!("Hello, world!"); +} +"#, + r#" +//- /main.rs +mod foo; +fn main() { + println!("Hello, world!"); +} +//- /foo.rs +fn f() { + +}"#, + ) + } + + #[test] + fn extract_module_to_file_with_lib_file() { + check_assist( + extract_module_to_file, + r#" +//- /lib.rs +mod foo {<|> + fn f() { + + } +} +fn main() { + println!("Hello, world!"); +} +"#, + r#" +//- /lib.rs +mod foo; +fn main() { + println!("Hello, world!"); +} +//- /foo.rs +fn f() { + +}"#, + ) + } +} diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs index 6e736ccb3..6b89b2d04 100644 --- a/crates/assists/src/lib.rs +++ b/crates/assists/src/lib.rs @@ -129,6 +129,7 @@ mod handlers { mod convert_integer_literal; mod early_return; mod expand_glob_import; + mod extract_module_to_file; mod extract_struct_from_enum_variant; mod extract_variable; mod fill_match_arms; @@ -179,6 +180,7 @@ mod handlers { convert_integer_literal::convert_integer_literal, early_return::convert_to_guarded_return, expand_glob_import::expand_glob_import, + extract_module_to_file::extract_module_to_file, extract_struct_from_enum_variant::extract_struct_from_enum_variant, extract_variable::extract_variable, fill_match_arms::fill_match_arms, diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs index cc7c4a343..e9093ec53 100644 --- a/crates/assists/src/tests/generated.rs +++ b/crates/assists/src/tests/generated.rs @@ -235,6 +235,21 @@ fn qux(bar: Bar, baz: Baz) {} ) } +#[test] +fn doctest_extract_module_to_file() { + check_doc_test( + "extract_module_to_file", + r#####" +mod foo {<|> + fn t() {} +} +"#####, + r#####" +mod foo; +"#####, + ) +} + #[test] fn doctest_extract_struct_from_enum_variant() { check_doc_test( -- cgit v1.2.3 From 7a2eebde22b1013b73706a11c4a89e969c36ed2b Mon Sep 17 00:00:00 2001 From: Daiki Ihara Date: Thu, 17 Dec 2020 22:09:55 +0900 Subject: Add initial_contents field for CreateFile --- crates/assists/src/assist_context.rs | 5 ++-- crates/assists/src/tests.rs | 52 +++++++++++------------------------- 2 files changed, 18 insertions(+), 39 deletions(-) (limited to 'crates/assists') diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs index cd22cf17d..80cf9aba1 100644 --- a/crates/assists/src/assist_context.rs +++ b/crates/assists/src/assist_context.rs @@ -285,10 +285,9 @@ impl AssistBuilder { } } pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into) { - let file_system_edit = FileSystemEdit::CreateFile { dst: dst.clone() }; + let file_system_edit = + FileSystemEdit::CreateFile { dst: dst.clone(), initial_contents: content.into() }; self.file_system_edits.push(file_system_edit); - self.edit_file(dst.anchor); - self.insert(TextSize::from(0), content) } fn finish(mut self) -> SourceChange { diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs index 9002040ce..d18e566e6 100644 --- a/crates/assists/src/tests.rs +++ b/crates/assists/src/tests.rs @@ -107,47 +107,27 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: && source_change.file_system_edits.len() == 0; source_change.source_file_edits.sort_by_key(|it| it.file_id); - let mut created_file_ids = Vec::new(); let mut buf = String::new(); - for file_system_edit in source_change.file_system_edits.clone() { - match file_system_edit { - FileSystemEdit::CreateFile { dst } => { - created_file_ids.push(dst.anchor); - } - _ => (), + for source_file_edit in source_change.source_file_edits { + let mut text = db.file_text(source_file_edit.file_id).as_ref().to_owned(); + source_file_edit.edit.apply(&mut text); + if !skip_header { + let sr = db.file_source_root(source_file_edit.file_id); + let sr = db.source_root(sr); + let path = sr.path_for_file(&source_file_edit.file_id).unwrap(); + format_to!(buf, "//- {}\n", path) } + buf.push_str(&text); } - for source_file_edit in source_change.source_file_edits { - if created_file_ids.contains(&source_file_edit.file_id) { - let target_dst = source_change - .file_system_edits - .iter() - .find_map(|f| match f { - FileSystemEdit::CreateFile { dst } => { - if dst.anchor == source_file_edit.file_id { - Some(&dst.path) - } else { - None - } - } - _ => None, - }) - .unwrap(); - format_to!(buf, "//- {}\n", target_dst); - let mut text = String::new(); - source_file_edit.edit.apply(&mut text); - buf.push_str(&text); - } else { - let mut text = db.file_text(source_file_edit.file_id).as_ref().to_owned(); - source_file_edit.edit.apply(&mut text); - if !skip_header { - let sr = db.file_source_root(source_file_edit.file_id); - let sr = db.source_root(sr); - let path = sr.path_for_file(&source_file_edit.file_id).unwrap(); - format_to!(buf, "//- {}\n", path) + for file_system_edit in source_change.file_system_edits.clone() { + match file_system_edit { + FileSystemEdit::CreateFile { dst, initial_contents } => { + let target_dst = dst.path; + format_to!(buf, "//- {}\n", target_dst); + buf.push_str(&initial_contents); } - buf.push_str(&text); + _ => (), } } -- cgit v1.2.3 From 66fd262962624db0a72f0aafff49a7c74601beb8 Mon Sep 17 00:00:00 2001 From: Daiki Ihara Date: Mon, 21 Dec 2020 15:50:59 +0900 Subject: Fix assist test logic --- crates/assists/src/tests.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'crates/assists') diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs index d18e566e6..b41f4874a 100644 --- a/crates/assists/src/tests.rs +++ b/crates/assists/src/tests.rs @@ -123,8 +123,12 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: for file_system_edit in source_change.file_system_edits.clone() { match file_system_edit { FileSystemEdit::CreateFile { dst, initial_contents } => { - let target_dst = dst.path; - format_to!(buf, "//- {}\n", target_dst); + let sr = db.file_source_root(dst.anchor); + let sr = db.source_root(sr); + let mut base = sr.path_for_file(&dst.anchor).unwrap().clone(); + base.pop(); + let created_file_path = format!("{}{}", base.to_string(), &dst.path[1..]); + format_to!(buf, "//- {}\n", created_file_path); buf.push_str(&initial_contents); } _ => (), -- cgit v1.2.3