mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
initial commit
This commit is contained in:
parent
533ca584c3
commit
0049b5b0bc
131
crates/ide_assists/src/handlers/move_from_mod_rs.rs
Normal file
131
crates/ide_assists/src/handlers/move_from_mod_rs.rs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
use ide_db::{
|
||||||
|
assists::{AssistId, AssistKind},
|
||||||
|
base_db::AnchoredPathBuf,
|
||||||
|
};
|
||||||
|
use syntax::{ast, AstNode, TextRange};
|
||||||
|
|
||||||
|
use crate::assist_context::{AssistContext, Assists};
|
||||||
|
use crate::utils::trimmed_text_range;
|
||||||
|
|
||||||
|
// Assist: move_from_mod_rs
|
||||||
|
//
|
||||||
|
// Moves xxx/mod.rs to xxx.rs.
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// //- /main.rs
|
||||||
|
// mod a;
|
||||||
|
// //- /a/mod.rs
|
||||||
|
// $0fn t() {}$0
|
||||||
|
// ```
|
||||||
|
// ->
|
||||||
|
// ```
|
||||||
|
// fn t() {}
|
||||||
|
// ```
|
||||||
|
pub(crate) fn move_from_mod_rs(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)?;
|
||||||
|
// Enable this assist if the user select all "meaningful" content in the source file
|
||||||
|
let trimmed_selected_range = trimmed_text_range(&source_file, ctx.frange.range);
|
||||||
|
let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range());
|
||||||
|
if !module.is_mod_rs(ctx.db()) {
|
||||||
|
cov_mark::hit!(not_mod_rs);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if trimmed_selected_range != trimmed_file_range {
|
||||||
|
cov_mark::hit!(not_all_selected);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let target = TextRange::new(
|
||||||
|
source_file.syntax().text_range().start(),
|
||||||
|
source_file.syntax().text_range().end(),
|
||||||
|
);
|
||||||
|
let module_name = module.name(ctx.db())?.to_string();
|
||||||
|
let path = format!("../{}.rs", module_name);
|
||||||
|
let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path };
|
||||||
|
acc.add(
|
||||||
|
AssistId("move_from_mod_rs", AssistKind::Refactor),
|
||||||
|
format!("Turn {}/mod.rs to {}.rs", module_name, module_name),
|
||||||
|
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(
|
||||||
|
move_from_mod_rs,
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
mod a;
|
||||||
|
//- /a/mod.rs
|
||||||
|
$0fn t() {}
|
||||||
|
$0"#,
|
||||||
|
r#"
|
||||||
|
//- /a.rs
|
||||||
|
fn t() {}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn must_select_all_file() {
|
||||||
|
cov_mark::check!(not_all_selected);
|
||||||
|
check_assist_not_applicable(
|
||||||
|
move_from_mod_rs,
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
mod a;
|
||||||
|
//- /a/mod.rs
|
||||||
|
fn t() {}$0
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
cov_mark::check!(not_all_selected);
|
||||||
|
check_assist_not_applicable(
|
||||||
|
move_from_mod_rs,
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
mod a;
|
||||||
|
//- /a/mod.rs
|
||||||
|
$0fn$0 t() {}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cannot_move_not_mod_rs() {
|
||||||
|
cov_mark::check!(not_mod_rs);
|
||||||
|
check_assist_not_applicable(
|
||||||
|
move_from_mod_rs,
|
||||||
|
r#"//- /main.rs
|
||||||
|
mod a;
|
||||||
|
//- /a.rs
|
||||||
|
$0fn t() {}$0
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cannot_downgrade_main_and_lib_rs() {
|
||||||
|
check_assist_not_applicable(
|
||||||
|
move_from_mod_rs,
|
||||||
|
r#"//- /main.rs
|
||||||
|
$0fn t() {}$0
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
check_assist_not_applicable(
|
||||||
|
move_from_mod_rs,
|
||||||
|
r#"//- /lib.rs
|
||||||
|
$0fn t() {}$0
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -2,38 +2,10 @@ use ide_db::{
|
|||||||
assists::{AssistId, AssistKind},
|
assists::{AssistId, AssistKind},
|
||||||
base_db::AnchoredPathBuf,
|
base_db::AnchoredPathBuf,
|
||||||
};
|
};
|
||||||
use syntax::{
|
use syntax::{ast, AstNode, TextRange};
|
||||||
ast::{self, Whitespace},
|
|
||||||
AstNode, AstToken, SourceFile, TextRange, TextSize,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::assist_context::{AssistContext, Assists};
|
use crate::assist_context::{AssistContext, Assists};
|
||||||
|
use crate::utils::trimmed_text_range;
|
||||||
/// Trim(remove leading and trailing whitespace) `initial_range` in `source_file`, return the trimmed range.
|
|
||||||
fn trimmed_text_range(source_file: &SourceFile, initial_range: TextRange) -> TextRange {
|
|
||||||
let mut trimmed_range = initial_range;
|
|
||||||
while source_file
|
|
||||||
.syntax()
|
|
||||||
.token_at_offset(trimmed_range.start())
|
|
||||||
.find_map(Whitespace::cast)
|
|
||||||
.is_some()
|
|
||||||
&& trimmed_range.start() < trimmed_range.end()
|
|
||||||
{
|
|
||||||
let start = trimmed_range.start() + TextSize::from(1);
|
|
||||||
trimmed_range = TextRange::new(start, trimmed_range.end());
|
|
||||||
}
|
|
||||||
while source_file
|
|
||||||
.syntax()
|
|
||||||
.token_at_offset(trimmed_range.end())
|
|
||||||
.find_map(Whitespace::cast)
|
|
||||||
.is_some()
|
|
||||||
&& trimmed_range.start() < trimmed_range.end()
|
|
||||||
{
|
|
||||||
let end = trimmed_range.end() - TextSize::from(1);
|
|
||||||
trimmed_range = TextRange::new(trimmed_range.start(), end);
|
|
||||||
}
|
|
||||||
trimmed_range
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assist: move_to_mod_rs
|
// Assist: move_to_mod_rs
|
||||||
//
|
//
|
||||||
|
@ -154,6 +154,7 @@ mod handlers {
|
|||||||
mod move_guard;
|
mod move_guard;
|
||||||
mod move_module_to_file;
|
mod move_module_to_file;
|
||||||
mod move_to_mod_rs;
|
mod move_to_mod_rs;
|
||||||
|
mod move_from_mod_rs;
|
||||||
mod pull_assignment_up;
|
mod pull_assignment_up;
|
||||||
mod qualify_path;
|
mod qualify_path;
|
||||||
mod raw_string;
|
mod raw_string;
|
||||||
@ -229,6 +230,7 @@ mod handlers {
|
|||||||
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,
|
||||||
move_to_mod_rs::move_to_mod_rs,
|
move_to_mod_rs::move_to_mod_rs,
|
||||||
|
move_from_mod_rs::move_from_mod_rs,
|
||||||
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,
|
||||||
|
@ -169,7 +169,7 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
|
|||||||
let sr = db.source_root(sr);
|
let sr = db.source_root(sr);
|
||||||
let mut base = sr.path_for_file(&dst.anchor).unwrap().clone();
|
let mut base = sr.path_for_file(&dst.anchor).unwrap().clone();
|
||||||
base.pop();
|
base.pop();
|
||||||
let created_file_path = format!("{}{}", base.to_string(), &dst.path[1..]);
|
let created_file_path = base.join(&dst.path).unwrap();
|
||||||
format_to!(buf, "//- {}\n", created_file_path);
|
format_to!(buf, "//- {}\n", created_file_path);
|
||||||
buf.push_str(&contents);
|
buf.push_str(&contents);
|
||||||
}
|
}
|
||||||
|
@ -1296,6 +1296,22 @@ fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn doctest_move_from_mod_rs() {
|
||||||
|
check_doc_test(
|
||||||
|
"move_from_mod_rs",
|
||||||
|
r#####"
|
||||||
|
//- /main.rs
|
||||||
|
mod a;
|
||||||
|
//- /a/mod.rs
|
||||||
|
$0fn t() {}$0
|
||||||
|
"#####,
|
||||||
|
r#####"
|
||||||
|
fn t() {}
|
||||||
|
"#####,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn doctest_move_guard_to_arm_body() {
|
fn doctest_move_guard_to_arm_body() {
|
||||||
check_doc_test(
|
check_doc_test(
|
||||||
|
@ -14,11 +14,11 @@ use syntax::{
|
|||||||
self,
|
self,
|
||||||
edit::{self, AstNodeEdit},
|
edit::{self, AstNodeEdit},
|
||||||
edit_in_place::AttrsOwnerEdit,
|
edit_in_place::AttrsOwnerEdit,
|
||||||
make, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds,
|
make, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace,
|
||||||
},
|
},
|
||||||
ted, AstNode, Direction, SmolStr,
|
ted, AstNode, AstToken, Direction, SmolStr, SourceFile,
|
||||||
SyntaxKind::*,
|
SyntaxKind::*,
|
||||||
SyntaxNode, TextSize, T,
|
SyntaxNode, TextRange, TextSize, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::assist_context::{AssistBuilder, AssistContext};
|
use crate::assist_context::{AssistBuilder, AssistContext};
|
||||||
@ -500,3 +500,29 @@ pub(crate) fn get_methods(items: &ast::AssocItemList) -> Vec<ast::Fn> {
|
|||||||
.filter(|f| f.name().is_some())
|
.filter(|f| f.name().is_some())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trim(remove leading and trailing whitespace) `initial_range` in `source_file`, return the trimmed range.
|
||||||
|
pub(crate) fn trimmed_text_range(source_file: &SourceFile, initial_range: TextRange) -> TextRange {
|
||||||
|
let mut trimmed_range = initial_range;
|
||||||
|
while source_file
|
||||||
|
.syntax()
|
||||||
|
.token_at_offset(trimmed_range.start())
|
||||||
|
.find_map(Whitespace::cast)
|
||||||
|
.is_some()
|
||||||
|
&& trimmed_range.start() < trimmed_range.end()
|
||||||
|
{
|
||||||
|
let start = trimmed_range.start() + TextSize::from(1);
|
||||||
|
trimmed_range = TextRange::new(start, trimmed_range.end());
|
||||||
|
}
|
||||||
|
while source_file
|
||||||
|
.syntax()
|
||||||
|
.token_at_offset(trimmed_range.end())
|
||||||
|
.find_map(Whitespace::cast)
|
||||||
|
.is_some()
|
||||||
|
&& trimmed_range.start() < trimmed_range.end()
|
||||||
|
{
|
||||||
|
let end = trimmed_range.end() - TextSize::from(1);
|
||||||
|
trimmed_range = TextRange::new(trimmed_range.start(), end);
|
||||||
|
}
|
||||||
|
trimmed_range
|
||||||
|
}
|
||||||
|
@ -359,6 +359,9 @@ impl VirtualPath {
|
|||||||
}
|
}
|
||||||
path = &path["../".len()..]
|
path = &path["../".len()..]
|
||||||
}
|
}
|
||||||
|
while path.starts_with("./") {
|
||||||
|
path = &path["./".len()..]
|
||||||
|
}
|
||||||
res.0 = format!("{}/{}", res.0, path);
|
res.0 = format!("{}/{}", res.0, path);
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user