rust-analyzer/crates/ide/src/ssr.rs
2021-03-10 06:02:15 -08:00

259 lines
7.4 KiB
Rust

//! This module provides an SSR assist. It is not desirable to include this
//! assist in ide_assists because that would require the ide_assists crate
//! depend on the ide_ssr crate.
use ide_assists::{Assist, AssistId, AssistKind, GroupLabel};
use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase};
pub(crate) fn add_ssr_assist(
db: &RootDatabase,
base: &mut Vec<Assist>,
resolve: bool,
frange: FileRange,
) -> Option<()> {
let (match_finder, comment_range) = ide_ssr::ssr_from_comment(db, frange)?;
let (source_change_for_file, source_change_for_workspace) = if resolve {
let edits = match_finder.edits();
let source_change_for_file = {
let text_edit_for_file = edits.get(&frange.file_id).cloned().unwrap_or_default();
SourceChange::from_text_edit(frange.file_id, text_edit_for_file)
};
let source_change_for_workspace = SourceChange::from(match_finder.edits());
(Some(source_change_for_file), Some(source_change_for_workspace))
} else {
(None, None)
};
let assists = vec![
("Apply SSR in file", source_change_for_file),
("Apply SSR in workspace", source_change_for_workspace),
];
for (label, source_change) in assists.into_iter() {
let assist = Assist {
id: AssistId("ssr", AssistKind::RefactorRewrite),
label: Label::new(label),
group: Some(GroupLabel("Apply SSR".into())),
target: comment_range,
source_change,
};
base.push(assist);
}
Some(())
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use expect_test::expect;
use ide_assists::Assist;
use ide_db::{
base_db::{fixture::WithFixture, salsa::Durability, FileRange},
symbol_index::SymbolsDatabase,
RootDatabase,
};
use rustc_hash::FxHashSet;
use super::add_ssr_assist;
fn get_assists(ra_fixture: &str, resolve: bool) -> Vec<Assist> {
let (mut db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture);
let mut local_roots = FxHashSet::default();
local_roots.insert(ide_db::base_db::fixture::WORKSPACE);
db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
let mut assists = vec![];
add_ssr_assist(
&db,
&mut assists,
resolve,
FileRange { file_id, range: range_or_offset.into() },
);
assists
}
#[test]
fn not_applicable_comment_not_ssr() {
let ra_fixture = r#"
//- /lib.rs
// This is foo $0
fn foo() {}
"#;
let resolve = true;
let assists = get_assists(ra_fixture, resolve);
assert_eq!(0, assists.len());
}
#[test]
fn resolve_edits_true() {
let resolve = true;
let assists = get_assists(
r#"
//- /lib.rs
mod bar;
// 2 ==>> 3$0
fn foo() { 2 }
//- /bar.rs
fn bar() { 2 }
"#,
resolve,
);
assert_eq!(2, assists.len());
let mut assists = assists.into_iter();
let apply_in_file_assist = assists.next().unwrap();
expect![[r#"
Assist {
id: AssistId(
"ssr",
RefactorRewrite,
),
label: "Apply SSR in file",
group: Some(
GroupLabel(
"Apply SSR",
),
),
target: 10..21,
source_change: Some(
SourceChange {
source_file_edits: {
FileId(
0,
): TextEdit {
indels: [
Indel {
insert: "3",
delete: 33..34,
},
],
},
},
file_system_edits: [],
is_snippet: false,
},
),
}
"#]]
.assert_debug_eq(&apply_in_file_assist);
let apply_in_workspace_assist = assists.next().unwrap();
expect![[r#"
Assist {
id: AssistId(
"ssr",
RefactorRewrite,
),
label: "Apply SSR in workspace",
group: Some(
GroupLabel(
"Apply SSR",
),
),
target: 10..21,
source_change: Some(
SourceChange {
source_file_edits: {
FileId(
0,
): TextEdit {
indels: [
Indel {
insert: "3",
delete: 33..34,
},
],
},
FileId(
1,
): TextEdit {
indels: [
Indel {
insert: "3",
delete: 11..12,
},
],
},
},
file_system_edits: [],
is_snippet: false,
},
),
}
"#]]
.assert_debug_eq(&apply_in_workspace_assist);
}
#[test]
fn resolve_edits_false() {
let resolve = false;
let assists = get_assists(
r#"
//- /lib.rs
mod bar;
// 2 ==>> 3$0
fn foo() { 2 }
//- /bar.rs
fn bar() { 2 }
"#,
resolve,
);
assert_eq!(2, assists.len());
let mut assists = assists.into_iter();
let apply_in_file_assist = assists.next().unwrap();
expect![[r#"
Assist {
id: AssistId(
"ssr",
RefactorRewrite,
),
label: "Apply SSR in file",
group: Some(
GroupLabel(
"Apply SSR",
),
),
target: 10..21,
source_change: None,
}
"#]]
.assert_debug_eq(&apply_in_file_assist);
let apply_in_workspace_assist = assists.next().unwrap();
expect![[r#"
Assist {
id: AssistId(
"ssr",
RefactorRewrite,
),
label: "Apply SSR in workspace",
group: Some(
GroupLabel(
"Apply SSR",
),
),
target: 10..21,
source_change: None,
}
"#]]
.assert_debug_eq(&apply_in_workspace_assist);
}
}