diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index cbf1963b72..77275156c8 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -1,8 +1,11 @@ //! This module defines `AssistCtx` -- the API surface that is exposed to assists. use hir::Semantics; -use ra_db::FileRange; +use ra_db::{FileId, FileRange}; use ra_fmt::{leading_indent, reindent}; -use ra_ide_db::RootDatabase; +use ra_ide_db::{ + source_change::{SingleFileChange, SourceChange}, + RootDatabase, +}; use ra_syntax::{ algo::{self, find_covering_element, find_node_at_offset, SyntaxRewriter}, AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize, @@ -10,7 +13,7 @@ use ra_syntax::{ }; use ra_text_edit::TextEditBuilder; -use crate::{AssistAction, AssistFile, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; +use crate::{AssistFile, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; #[derive(Clone, Debug)] pub(crate) struct Assist(pub(crate) Vec); @@ -19,7 +22,7 @@ pub(crate) struct Assist(pub(crate) Vec); pub(crate) struct AssistInfo { pub(crate) label: AssistLabel, pub(crate) group_label: Option, - pub(crate) action: Option, + pub(crate) action: Option, } impl AssistInfo { @@ -27,7 +30,7 @@ impl AssistInfo { AssistInfo { label, group_label: None, action: None } } - fn resolved(self, action: AssistAction) -> AssistInfo { + fn resolved(self, action: SourceChange) -> AssistInfo { AssistInfo { action: Some(action), ..self } } @@ -98,13 +101,13 @@ impl<'a> AssistCtx<'a> { f: impl FnOnce(&mut ActionBuilder), ) -> Option { let label = AssistLabel::new(id, label.into(), None, target); - + let change_label = label.label.clone(); let mut info = AssistInfo::new(label); if self.should_compute_edit { let action = { let mut edit = ActionBuilder::new(&self); f(&mut edit); - edit.build() + edit.build(change_label, self.frange.file_id) }; info = info.resolved(action) }; @@ -157,13 +160,13 @@ impl<'a> AssistGroup<'a> { f: impl FnOnce(&mut ActionBuilder), ) { let label = AssistLabel::new(id, label.into(), Some(self.group.clone()), target); - + let change_label = label.label.clone(); let mut info = AssistInfo::new(label).with_group(self.group.clone()); if self.ctx.should_compute_edit { let action = { let mut edit = ActionBuilder::new(&self.ctx); f(&mut edit); - edit.build() + edit.build(change_label, self.ctx.frange.file_id) }; info = info.resolved(action) }; @@ -255,11 +258,16 @@ impl<'a, 'b> ActionBuilder<'a, 'b> { self.file = assist_file } - fn build(self) -> AssistAction { + fn build(self, change_label: String, current_file: FileId) -> SourceChange { let edit = self.edit.finish(); if edit.is_empty() && self.cursor_position.is_none() { panic!("Only call `add_assist` if the assist can be applied") } - AssistAction { edit, cursor_position: self.cursor_position, file: self.file } + let file = match self.file { + AssistFile::CurrentFile => current_file, + AssistFile::TargetFile(it) => it, + }; + SingleFileChange { label: change_label, edit, cursor_position: self.cursor_position } + .into_source_change(file) } } diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index f4f37614ff..8cd8f89c42 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -19,9 +19,8 @@ pub mod ast_transform; use hir::Semantics; use ra_db::{FileId, FileRange}; -use ra_ide_db::RootDatabase; -use ra_syntax::{TextRange, TextSize}; -use ra_text_edit::TextEdit; +use ra_ide_db::{source_change::SourceChange, RootDatabase}; +use ra_syntax::TextRange; pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; @@ -57,21 +56,14 @@ impl AssistLabel { } } -#[derive(Debug, Clone)] -pub struct AssistAction { - pub edit: TextEdit, - pub cursor_position: Option, - pub file: AssistFile, -} - #[derive(Debug, Clone)] pub struct ResolvedAssist { pub label: AssistLabel, - pub action: AssistAction, + pub action: SourceChange, } #[derive(Debug, Clone, Copy)] -pub enum AssistFile { +enum AssistFile { CurrentFile, TargetFile(FileId), } diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs index dd9026df61..572462bfc4 100644 --- a/crates/ra_assists/src/tests.rs +++ b/crates/ra_assists/src/tests.rs @@ -11,7 +11,7 @@ use test_utils::{ RangeOrOffset, }; -use crate::{handlers::Handler, resolved_assists, AssistCtx, AssistFile}; +use crate::{handlers::Handler, resolved_assists, AssistCtx}; pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { let (mut db, file_id) = RootDatabase::with_single_file(text); @@ -41,7 +41,7 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) { let (db, file_id) = crate::tests::with_single_file(&before); let frange = FileRange { file_id, range: selection.into() }; - let assist = resolved_assists(&db, frange) + let mut assist = resolved_assists(&db, frange) .into_iter() .find(|assist| assist.label.id.0 == assist_id) .unwrap_or_else(|| { @@ -57,8 +57,9 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) { }); let actual = { + let change = assist.action.source_file_edits.pop().unwrap(); let mut actual = before.clone(); - assist.action.edit.apply(&mut actual); + change.edit.apply(&mut actual); actual }; assert_eq_text!(after, &actual); @@ -93,26 +94,23 @@ fn check(assist: Handler, before: &str, expected: ExpectedResult) { match (assist(assist_ctx), expected) { (Some(assist), ExpectedResult::After(after)) => { - let action = assist.0[0].action.clone().unwrap(); + let mut action = assist.0[0].action.clone().unwrap(); + let change = action.source_file_edits.pop().unwrap(); - let mut actual = if let AssistFile::TargetFile(file_id) = action.file { - db.file_text(file_id).as_ref().to_owned() - } else { - text_without_caret - }; - action.edit.apply(&mut actual); + let mut actual = db.file_text(change.file_id).as_ref().to_owned(); + change.edit.apply(&mut actual); match action.cursor_position { None => { if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { - let off = action + let off = change .edit .apply_to_offset(before_cursor_pos) .expect("cursor position is affected by the edit"); actual = add_cursor(&actual, off) } } - Some(off) => actual = add_cursor(&actual, off), + Some(off) => actual = add_cursor(&actual, off.offset), }; assert_eq_text!(after, &actual); diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs deleted file mode 100644 index 389339a034..0000000000 --- a/crates/ra_ide/src/assists.rs +++ /dev/null @@ -1,42 +0,0 @@ -//! FIXME: write short doc here - -use ra_assists::{resolved_assists, AssistAction}; -use ra_db::{FilePosition, FileRange}; -use ra_ide_db::RootDatabase; - -use crate::{FileId, SourceChange, SourceFileEdit}; - -pub use ra_assists::AssistId; - -#[derive(Debug)] -pub struct Assist { - pub id: AssistId, - pub label: String, - pub group_label: Option, - pub source_change: SourceChange, -} - -pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec { - resolved_assists(db, frange) - .into_iter() - .map(|assist| { - let file_id = frange.file_id; - Assist { - id: assist.label.id, - label: assist.label.label.clone(), - group_label: assist.label.group.map(|it| it.0), - source_change: action_to_edit(assist.action, file_id, assist.label.label.clone()), - } - }) - .collect() -} - -fn action_to_edit(action: AssistAction, file_id: FileId, label: String) -> SourceChange { - let file_id = match action.file { - ra_assists::AssistFile::TargetFile(it) => it, - _ => file_id, - }; - let file_edit = SourceFileEdit { file_id, edit: action.edit }; - SourceChange::source_file_edit(label, file_edit) - .with_cursor_opt(action.cursor_position.map(|offset| FilePosition { offset, file_id })) -} diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 4ed02f60ef..614029de46 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -31,7 +31,6 @@ mod syntax_highlighting; mod parent_module; mod references; mod impls; -mod assists; mod diagnostics; mod syntax_tree; mod folding_ranges; @@ -64,7 +63,6 @@ use ra_syntax::{SourceFile, TextRange, TextSize}; use crate::display::ToNav; pub use crate::{ - assists::{Assist, AssistId}, call_hierarchy::CallItem, completion::{ CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, @@ -84,6 +82,7 @@ pub use crate::{ }; pub use hir::Documentation; +pub use ra_assists::AssistId; pub use ra_db::{ Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId, }; @@ -134,10 +133,12 @@ pub struct AnalysisHost { db: RootDatabase, } -impl Default for AnalysisHost { - fn default() -> AnalysisHost { - AnalysisHost::new(None) - } +#[derive(Debug)] +pub struct Assist { + pub id: AssistId, + pub label: String, + pub group_label: Option, + pub source_change: SourceChange, } impl AnalysisHost { @@ -187,6 +188,12 @@ impl AnalysisHost { } } +impl Default for AnalysisHost { + fn default() -> AnalysisHost { + AnalysisHost::new(None) + } +} + /// Analysis is a snapshot of a world state at a moment in time. It is the main /// entry point for asking semantic information about the world. When the world /// state is advanced using `AnalysisHost::apply_change` method, all existing @@ -464,7 +471,17 @@ impl Analysis { /// Computes assists (aka code actions aka intentions) for the given /// position. pub fn assists(&self, frange: FileRange) -> Cancelable> { - self.with_db(|db| assists::assists(db, frange)) + self.with_db(|db| { + ra_assists::resolved_assists(db, frange) + .into_iter() + .map(|assist| Assist { + id: assist.label.id, + label: assist.label.label, + group_label: assist.label.group.map(|it| it.0), + source_change: assist.action, + }) + .collect() + }) } /// Computes the set of diagnostics for the given file. diff --git a/crates/ra_ide_db/src/source_change.rs b/crates/ra_ide_db/src/source_change.rs index 4dd01b3122..af81a91a4a 100644 --- a/crates/ra_ide_db/src/source_change.rs +++ b/crates/ra_ide_db/src/source_change.rs @@ -6,7 +6,7 @@ use ra_db::{FileId, FilePosition, RelativePathBuf, SourceRootId}; use ra_text_edit::{TextEdit, TextSize}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SourceChange { /// For display in the undo log in the editor pub label: String, @@ -90,13 +90,13 @@ impl SourceChange { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SourceFileEdit { pub file_id: FileId, pub edit: TextEdit, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum FileSystemEdit { CreateFile { source_root: SourceRootId, path: RelativePathBuf }, MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf },