Add promote_mod_file assist

This commit is contained in:
longfangsong 2021-09-12 02:30:56 +08:00
parent d270679997
commit fede1a3beb
4 changed files with 167 additions and 10 deletions

View File

@ -294,6 +294,10 @@ pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into<St
let file_system_edit = FileSystemEdit::CreateFile { dst, initial_contents: content.into() }; let file_system_edit = FileSystemEdit::CreateFile { dst, initial_contents: content.into() };
self.source_change.push_file_system_edit(file_system_edit); self.source_change.push_file_system_edit(file_system_edit);
} }
pub(crate) fn move_file(&mut self, src: FileId, dst: AnchoredPathBuf) {
let file_system_edit = FileSystemEdit::MoveFile { src, dst };
self.source_change.push_file_system_edit(file_system_edit);
}
fn finish(mut self) -> SourceChange { fn finish(mut self) -> SourceChange {
self.commit(); self.commit();

View File

@ -0,0 +1,148 @@
use ide_db::{
assists::{AssistId, AssistKind},
base_db::AnchoredPathBuf,
};
use syntax::{
ast::{self},
AstNode, TextRange,
};
use crate::assist_context::{AssistContext, Assists};
pub(crate) fn promote_mod_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?;
let module = ctx.sema.to_module_def(ctx.frange.file_id)?;
if module.is_mod_rs(ctx.db()) {
return None;
}
let target = TextRange::new(
source_file.syntax().text_range().start(),
source_file.syntax().text_range().end(),
);
let path = format!("./{}/mod.rs", module.name(ctx.db())?.to_string());
let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path };
acc.add(
AssistId("promote_mod_file", AssistKind::Refactor),
"Promote Module to directory",
target,
|builder| {
builder.move_file(ctx.frange.file_id, dst);
},
)
}
#[cfg(test)]
mod tests {
use crate::tests::{check_assist, check_assist_not_applicable};
use super::*;
#[test]
fn trivial() {
check_assist(
promote_mod_file,
r#"
//- /main.rs
mod a;
//- /a.rs
$0fn t() {}
"#,
r#"
//- /a/mod.rs
fn t() {}
"#,
);
}
#[test]
fn cursor_can_be_putted_anywhere() {
check_assist(
promote_mod_file,
r#"
//- /main.rs
mod a;
//- /a.rs
fn t() {}$0
"#,
r#"
//- /a/mod.rs
fn t() {}
"#,
);
check_assist(
promote_mod_file,
r#"
//- /main.rs
mod a;
//- /a.rs
fn t()$0 {}
"#,
r#"
//- /a/mod.rs
fn t() {}
"#,
);
check_assist(
promote_mod_file,
r#"
//- /main.rs
mod a;
//- /a.rs
fn t($0) {}
"#,
r#"
//- /a/mod.rs
fn t() {}
"#,
);
}
#[test]
fn cannot_promote_mod_rs() {
check_assist_not_applicable(
promote_mod_file,
r#"//- /main.rs
mod a;
//- /a/mod.rs
$0fn t() {}
"#,
);
}
#[test]
fn cannot_promote_main_and_lib_rs() {
check_assist_not_applicable(
promote_mod_file,
r#"//- /main.rs
$0fn t() {}
"#,
);
check_assist_not_applicable(
promote_mod_file,
r#"//- /lib.rs
$0fn t() {}
"#,
);
}
#[test]
fn works_in_mod() {
// note: /a/b.rs remains untouched
check_assist(
promote_mod_file,
r#"//- /main.rs
mod a;
//- /a.rs
mod b;
$0fn t() {}
//- /a/b.rs
fn t1() {}
"#,
r#"
//- /a/mod.rs
mod b;
fn t() {}
"#,
);
}
}

View File

@ -96,6 +96,7 @@ mod handlers {
mod move_bounds; mod move_bounds;
mod move_guard; mod move_guard;
mod move_module_to_file; mod move_module_to_file;
mod promote_mod_file;
mod pull_assignment_up; mod pull_assignment_up;
mod qualify_path; mod qualify_path;
mod raw_string; mod raw_string;
@ -167,6 +168,7 @@ pub(crate) fn all() -> &'static [Handler] {
move_guard::move_arm_cond_to_match_guard, move_guard::move_arm_cond_to_match_guard,
move_guard::move_guard_to_arm_body, move_guard::move_guard_to_arm_body,
move_module_to_file::move_module_to_file, move_module_to_file::move_module_to_file,
promote_mod_file::promote_mod_file,
pull_assignment_up::pull_assignment_up, pull_assignment_up::pull_assignment_up,
qualify_path::qualify_path, qualify_path::qualify_path,
raw_string::add_hash, raw_string::add_hash,

View File

@ -142,7 +142,6 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
(Some(assist), ExpectedResult::After(after)) => { (Some(assist), ExpectedResult::After(after)) => {
let source_change = let source_change =
assist.source_change.expect("Assist did not contain any source changes"); assist.source_change.expect("Assist did not contain any source changes");
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.file_system_edits.len() == 0;
@ -160,15 +159,19 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
} }
for file_system_edit in source_change.file_system_edits { for file_system_edit in source_change.file_system_edits {
if let FileSystemEdit::CreateFile { dst, initial_contents } = file_system_edit { let (dst, contents) = match file_system_edit {
let sr = db.file_source_root(dst.anchor); FileSystemEdit::CreateFile { dst, initial_contents } => (dst, initial_contents),
let sr = db.source_root(sr); FileSystemEdit::MoveFile { src, dst } => {
let mut base = sr.path_for_file(&dst.anchor).unwrap().clone(); (dst, db.file_text(src).as_ref().to_owned())
base.pop(); }
let created_file_path = format!("{}{}", base.to_string(), &dst.path[1..]); };
format_to!(buf, "//- {}\n", created_file_path); let sr = db.file_source_root(dst.anchor);
buf.push_str(&initial_contents); 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(&contents);
} }
assert_eq_text!(after, &buf); assert_eq_text!(after, &buf);