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

252 lines
7.5 KiB
Rust
Raw Normal View History

2021-03-09 05:11:28 +00:00
//! 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.
2021-05-03 14:08:09 +00:00
use ide_assists::{Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel};
2021-03-09 05:11:28 +00:00
use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase};
2021-05-03 14:08:09 +00:00
pub(crate) fn ssr_assists(
2021-03-09 05:11:28 +00:00
db: &RootDatabase,
2021-05-03 15:03:28 +00:00
resolve: &AssistResolveStrategy,
2021-03-09 05:11:28 +00:00
frange: FileRange,
2021-05-03 14:08:09 +00:00
) -> Vec<Assist> {
let mut ssr_assists = Vec::with_capacity(2);
2021-03-09 05:11:28 +00:00
2021-05-03 14:08:09 +00:00
let (match_finder, comment_range) = match ide_ssr::ssr_from_comment(db, frange) {
2021-05-03 15:44:58 +00:00
Some(ssr_data) => ssr_data,
2021-05-03 14:08:09 +00:00
None => return ssr_assists,
};
let id = AssistId("ssr", AssistKind::RefactorRewrite);
let (source_change_for_file, source_change_for_workspace) = if resolve.should_resolve(&id) {
2021-03-09 05:11:28 +00:00
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 {
2021-05-03 14:08:09 +00:00
id,
label: Label::new(label.to_string()),
2021-03-09 05:11:28 +00:00
group: Some(GroupLabel("Apply SSR".into())),
target: comment_range,
source_change,
};
2021-05-03 14:08:09 +00:00
ssr_assists.push(assist);
2021-03-09 05:11:28 +00:00
}
2021-05-03 14:08:09 +00:00
ssr_assists
2021-03-09 05:11:28 +00:00
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use expect_test::expect;
2021-05-03 14:08:09 +00:00
use ide_assists::{Assist, AssistResolveStrategy};
2021-03-09 05:11:28 +00:00
use ide_db::{
base_db::{fixture::WithFixture, salsa::Durability, FileRange},
symbol_index::SymbolsDatabase,
RootDatabase,
};
use rustc_hash::FxHashSet;
2021-05-03 14:08:09 +00:00
use super::ssr_assists;
2021-03-09 05:11:28 +00:00
2021-05-03 14:08:09 +00:00
fn get_assists(ra_fixture: &str, resolve: AssistResolveStrategy) -> Vec<Assist> {
2021-03-09 05:11:28 +00:00
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);
2021-05-03 15:03:28 +00:00
ssr_assists(&db, &resolve, FileRange { file_id, range: range_or_offset.into() })
2021-03-09 05:11:28 +00:00
}
#[test]
fn not_applicable_comment_not_ssr() {
let ra_fixture = r#"
//- /lib.rs
// This is foo $0
fn foo() {}
"#;
2021-05-03 14:08:09 +00:00
let assists = get_assists(ra_fixture, AssistResolveStrategy::All);
2021-03-09 05:11:28 +00:00
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 }
"#,
2021-05-03 14:08:09 +00:00
AssistResolveStrategy::All,
2021-03-09 05:11:28 +00:00
);
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 assists = get_assists(
r#"
//- /lib.rs
mod bar;
// 2 ==>> 3$0
fn foo() { 2 }
//- /bar.rs
fn bar() { 2 }
"#,
2021-05-03 14:08:09 +00:00
AssistResolveStrategy::None,
2021-03-09 05:11:28 +00:00
);
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);
}
}