rust-analyzer/crates/ide/src/ssr.rs

264 lines
8.1 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, AssistResolveStrategy, GroupLabel};
use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase};
pub(crate) fn ssr_assists(
db: &RootDatabase,
resolve: &AssistResolveStrategy,
frange: FileRange,
) -> Vec<Assist> {
let mut ssr_assists = Vec::with_capacity(2);
let (match_finder, comment_range) = match ide_ssr::ssr_from_comment(db, frange) {
Some(ssr_data) => ssr_data,
None => return ssr_assists,
};
let id = AssistId("ssr", AssistKind::RefactorRewrite);
let (source_change_for_file, source_change_for_workspace) = if resolve.should_resolve(&id) {
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,
label: Label::new(label.to_string()),
group: Some(GroupLabel("Apply SSR".into())),
target: comment_range,
source_change,
trigger_signature_help: false,
};
ssr_assists.push(assist);
}
ssr_assists
}
#[cfg(test)]
mod tests {
use expect_test::expect;
use ide_assists::{Assist, AssistResolveStrategy};
use ide_db::{
base_db::{salsa::Durability, FileRange},
symbol_index::SymbolsDatabase,
FxHashSet, RootDatabase,
};
use test_fixture::WithFixture;
use triomphe::Arc;
use super::ssr_assists;
fn get_assists(ra_fixture: &str, resolve: AssistResolveStrategy) -> 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(test_fixture::WORKSPACE);
db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
ssr_assists(&db, &resolve, FileRange { file_id, range: range_or_offset.into() })
}
#[test]
fn not_applicable_comment_not_ssr() {
let ra_fixture = r#"
//- /lib.rs
// This is foo $0
fn foo() {}
"#;
let assists = get_assists(ra_fixture, AssistResolveStrategy::All);
assert_eq!(0, assists.len());
}
#[test]
fn resolve_edits_true() {
let assists = get_assists(
r#"
//- /lib.rs
mod bar;
// 2 ==>> 3$0
fn foo() { 2 }
//- /bar.rs
fn bar() { 2 }
"#,
AssistResolveStrategy::All,
);
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,
},
],
},
None,
),
},
file_system_edits: [],
is_snippet: false,
},
),
trigger_signature_help: 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,
},
],
},
None,
),
FileId(
1,
): (
TextEdit {
indels: [
Indel {
insert: "3",
delete: 11..12,
},
],
},
None,
),
},
file_system_edits: [],
is_snippet: false,
},
),
trigger_signature_help: false,
}
"#]]
.assert_debug_eq(&apply_in_workspace_assist);
}
#[test]
fn resolve_edits_false() {
let assists = get_assists(
r#"
//- /lib.rs
mod bar;
// 2 ==>> 3$0
fn foo() { 2 }
//- /bar.rs
fn bar() { 2 }
"#,
AssistResolveStrategy::None,
);
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,
trigger_signature_help: 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: None,
trigger_signature_help: false,
}
"#]]
.assert_debug_eq(&apply_in_workspace_assist);
}
}