diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs index cd22cf17da2..80cf9aba11f 100644 --- a/crates/assists/src/assist_context.rs +++ b/crates/assists/src/assist_context.rs @@ -285,10 +285,9 @@ impl AssistBuilder { } } pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into) { - let file_system_edit = FileSystemEdit::CreateFile { dst: dst.clone() }; + let file_system_edit = + FileSystemEdit::CreateFile { dst: dst.clone(), initial_contents: content.into() }; self.file_system_edits.push(file_system_edit); - self.edit_file(dst.anchor); - self.insert(TextSize::from(0), content) } fn finish(mut self) -> SourceChange { diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs index 9002040ce4d..d18e566e616 100644 --- a/crates/assists/src/tests.rs +++ b/crates/assists/src/tests.rs @@ -107,47 +107,27 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: && source_change.file_system_edits.len() == 0; source_change.source_file_edits.sort_by_key(|it| it.file_id); - let mut created_file_ids = Vec::new(); let mut buf = String::new(); - for file_system_edit in source_change.file_system_edits.clone() { - match file_system_edit { - FileSystemEdit::CreateFile { dst } => { - created_file_ids.push(dst.anchor); - } - _ => (), + for source_file_edit in source_change.source_file_edits { + let mut text = db.file_text(source_file_edit.file_id).as_ref().to_owned(); + source_file_edit.edit.apply(&mut text); + if !skip_header { + let sr = db.file_source_root(source_file_edit.file_id); + let sr = db.source_root(sr); + let path = sr.path_for_file(&source_file_edit.file_id).unwrap(); + format_to!(buf, "//- {}\n", path) } + buf.push_str(&text); } - for source_file_edit in source_change.source_file_edits { - if created_file_ids.contains(&source_file_edit.file_id) { - let target_dst = source_change - .file_system_edits - .iter() - .find_map(|f| match f { - FileSystemEdit::CreateFile { dst } => { - if dst.anchor == source_file_edit.file_id { - Some(&dst.path) - } else { - None - } - } - _ => None, - }) - .unwrap(); - format_to!(buf, "//- {}\n", target_dst); - let mut text = String::new(); - source_file_edit.edit.apply(&mut text); - buf.push_str(&text); - } else { - let mut text = db.file_text(source_file_edit.file_id).as_ref().to_owned(); - source_file_edit.edit.apply(&mut text); - if !skip_header { - let sr = db.file_source_root(source_file_edit.file_id); - let sr = db.source_root(sr); - let path = sr.path_for_file(&source_file_edit.file_id).unwrap(); - format_to!(buf, "//- {}\n", path) + for file_system_edit in source_change.file_system_edits.clone() { + match file_system_edit { + FileSystemEdit::CreateFile { dst, initial_contents } => { + let target_dst = dst.path; + format_to!(buf, "//- {}\n", target_dst); + buf.push_str(&initial_contents); } - buf.push_str(&text); + _ => (), } } diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index e8b89662385..d79f5c17006 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs @@ -40,6 +40,7 @@ impl DiagnosticWithFix for UnresolvedModule { anchor: self.file.original_file(sema.db), path: self.candidate.clone(), }, + initial_contents: "".to_string(), } .into(), unresolved_module.syntax().text_range(), diff --git a/crates/ide_db/src/source_change.rs b/crates/ide_db/src/source_change.rs index e87d98dadcf..10c0abdacae 100644 --- a/crates/ide_db/src/source_change.rs +++ b/crates/ide_db/src/source_change.rs @@ -44,7 +44,7 @@ impl From> for SourceChange { #[derive(Debug, Clone)] pub enum FileSystemEdit { - CreateFile { dst: AnchoredPathBuf }, + CreateFile { dst: AnchoredPathBuf, initial_contents: String }, MoveFile { src: FileId, dst: AnchoredPathBuf }, } diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index e0561b5a7a8..5a1ae96aa09 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -634,30 +634,47 @@ pub(crate) fn snippet_text_document_edit( Ok(lsp_ext::SnippetTextDocumentEdit { text_document, edits }) } -pub(crate) fn resource_op( +pub(crate) fn snippet_text_document_ops( snap: &GlobalStateSnapshot, file_system_edit: FileSystemEdit, -) -> lsp_types::ResourceOp { +) -> Vec { + let mut ops = Vec::new(); match file_system_edit { - FileSystemEdit::CreateFile { dst } => { + FileSystemEdit::CreateFile { dst, initial_contents } => { let uri = snap.anchored_path(&dst); - lsp_types::ResourceOp::Create(lsp_types::CreateFile { - uri, + let create_file = lsp_types::ResourceOp::Create(lsp_types::CreateFile { + uri: uri.clone(), options: None, annotation_id: None, - }) + }); + ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(create_file)); + if !initial_contents.is_empty() { + let text_document = + lsp_types::OptionalVersionedTextDocumentIdentifier { uri, version: None }; + let range = range(&LineIndex::new(""), TextRange::empty(TextSize::from(0))); + let text_edit = lsp_ext::SnippetTextEdit { + range, + new_text: initial_contents, + insert_text_format: Some(lsp_types::InsertTextFormat::PlainText), + }; + let edit_file = + lsp_ext::SnippetTextDocumentEdit { text_document, edits: vec![text_edit] }; + ops.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit_file)); + } } FileSystemEdit::MoveFile { src, dst } => { let old_uri = snap.file_id_to_url(src); let new_uri = snap.anchored_path(&dst); - lsp_types::ResourceOp::Rename(lsp_types::RenameFile { + let rename_file = lsp_types::ResourceOp::Rename(lsp_types::RenameFile { old_uri, new_uri, options: None, annotation_id: None, - }) + }); + ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(rename_file)) } } + ops } pub(crate) fn snippet_workspace_edit( @@ -666,8 +683,8 @@ pub(crate) fn snippet_workspace_edit( ) -> Result { let mut document_changes: Vec = Vec::new(); for op in source_change.file_system_edits { - let op = resource_op(&snap, op); - document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Op(op)); + let ops = snippet_text_document_ops(snap, op); + document_changes.extend_from_slice(&ops); } for edit in source_change.source_file_edits { let edit = snippet_text_document_edit(&snap, source_change.is_snippet, edit)?;