Repository: rust-analyzer/rust-analyzer
Pull request #309 (2018-12-21 09:33:27)

Fix edits


Patch:
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index cefe5a748e..5701e1ae23 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -368,10 +368,11 @@ impl AnalysisImpl {
             .collect::<Vec<_>>();
         if let Some(m) = source_binder::module_from_file_id(&*self.db, file_id)? {
             for (name_node, problem) in m.problems(&*self.db) {
+                let source_root = self.db.file_source_root(file_id);
                 let diag = match problem {
                     Problem::UnresolvedModule { candidate } => {
                         let create_file = FileSystemEdit::CreateFile {
-                            anchor: file_id,
+                            source_root,
                             path: candidate.clone(),
                         };
                         let fix = SourceChange {
@@ -388,11 +389,12 @@ impl AnalysisImpl {
                     }
                     Problem::NotDirOwner { move_to, candidate } => {
                         let move_file = FileSystemEdit::MoveFile {
-                            file: file_id,
-                            path: move_to.clone(),
+                            src: file_id,
+                            dst_source_root: source_root,
+                            dst_path: move_to.clone(),
                         };
                         let create_file = FileSystemEdit::CreateFile {
-                            anchor: file_id,
+                            source_root,
                             path: move_to.join(candidate),
                         };
                         let fix = SourceChange {
@@ -520,7 +522,7 @@ impl SourceChange {
     pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange {
         let file_edit = SourceFileEdit {
             file_id,
-            edits: edit.edit.into_atoms(),
+            edit: edit.edit,
         };
         SourceChange {
             label: label.to_string(),
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index d5725ef2e5..c7e7dc1c03 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -20,7 +20,7 @@ use std::{fmt, sync::Arc};
 
 use rustc_hash::FxHashMap;
 use ra_syntax::{SourceFileNode, TextRange, TextUnit};
-use ra_text_edit::AtomTextEdit;
+use ra_text_edit::TextEdit;
 use rayon::prelude::*;
 use relative_path::RelativePathBuf;
 
@@ -167,18 +167,19 @@ pub struct SourceChange {
 #[derive(Debug)]
 pub struct SourceFileEdit {
     pub file_id: FileId,
-    pub edits: Vec<AtomTextEdit>,
+    pub edit: TextEdit,
 }
 
 #[derive(Debug)]
 pub enum FileSystemEdit {
     CreateFile {
-        anchor: FileId,
+        source_root: SourceRootId,
         path: RelativePathBuf,
     },
     MoveFile {
-        file: FileId,
-        path: RelativePathBuf,
+        src: FileId,
+        dst_source_root: SourceRootId,
+        dst_path: RelativePathBuf,
     },
 }
 
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs
index f3a346152b..748fdb64e2 100644
--- a/crates/ra_hir/src/module/imp.rs
+++ b/crates/ra_hir/src/module/imp.rs
@@ -4,7 +4,7 @@ use ra_syntax::{
     ast::{self, NameOwner},
     SmolStr,
 };
-use relative_path::{RelativePathBuf, RelativePath};
+use relative_path::RelativePathBuf;
 use rustc_hash::{FxHashMap, FxHashSet};
 use arrayvec::ArrayVec;
 use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId};
@@ -184,11 +184,7 @@ fn resolve_submodule(
         .collect::<Vec<_>>();
     let problem = if points_to.is_empty() {
         Some(Problem::UnresolvedModule {
-            candidate: RelativePath::new("../").join(&if is_dir_owner {
-                file_mod
-            } else {
-                file_dir_mod
-            }),
+            candidate: if is_dir_owner { file_mod } else { file_dir_mod },
         })
     } else {
         None
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 198dbfc495..218ded4eec 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -97,21 +97,21 @@ impl ConvWith for TextEdit {
     type Output = Vec<languageserver_types::TextEdit>;
 
     fn conv_with(self, line_index: &LineIndex) -> Vec<languageserver_types::TextEdit> {
-        self.into_atoms()
+        self.as_atoms()
             .into_iter()
             .map_conv_with(line_index)
             .collect()
     }
 }
 
-impl ConvWith for AtomTextEdit {
+impl<'a> ConvWith for &'a AtomTextEdit {
     type Ctx = LineIndex;
     type Output = languageserver_types::TextEdit;
 
     fn conv_with(self, line_index: &LineIndex) -> languageserver_types::TextEdit {
         languageserver_types::TextEdit {
             range: self.delete.conv_with(line_index),
-            new_text: self.insert,
+            new_text: self.insert.clone(),
         }
     }
 }
@@ -199,7 +199,7 @@ impl TryConvWith for SourceChange {
                     .source_file_edits
                     .iter()
                     .find(|it| it.file_id == pos.file_id)
-                    .map(|it| it.edits.as_slice())
+                    .map(|it| it.edit.as_atoms())
                     .unwrap_or(&[]);
                 let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits);
                 let position =
@@ -265,7 +265,12 @@ impl TryConvWith for SourceFileEdit {
             version: None,
         };
         let line_index = world.analysis().file_line_index(self.file_id);
-        let edits = self.edits.into_iter().map_conv_with(&line_index).collect();
+        let edits = self
+            .edit
+            .as_atoms()
+            .iter()
+            .map_conv_with(&line_index)
+            .collect();
         Ok(TextDocumentEdit {
             text_document,
             edits,
@@ -278,16 +283,17 @@ impl TryConvWith for FileSystemEdit {
     type Output = req::FileSystemEdit;
     fn try_conv_with(self, world: &ServerWorld) -> Result<req::FileSystemEdit> {
         let res = match self {
-            FileSystemEdit::CreateFile { anchor, path } => {
-                let uri = world.file_id_to_uri(anchor)?;
-                let path = &path.as_str()[3..]; // strip `../` b/c url is weird
-                let uri = uri.join(path)?;
+            FileSystemEdit::CreateFile { source_root, path } => {
+                let uri = world.path_to_uri(source_root, &path)?;
                 req::FileSystemEdit::CreateFile { uri }
             }
-            FileSystemEdit::MoveFile { file, path } => {
-                let src = world.file_id_to_uri(file)?;
-                let path = &path.as_str()[3..]; // strip `../` b/c url is weird
-                let dst = src.join(path)?;
+            FileSystemEdit::MoveFile {
+                src,
+                dst_source_root,
+                dst_path,
+            } => {
+                let src = world.file_id_to_uri(src)?;
+                let dst = world.path_to_uri(dst_source_root, &dst_path)?;
                 req::FileSystemEdit::MoveFile { src, dst }
             }
         };
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 801966304c..1751d7fa81 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -107,9 +107,16 @@ pub fn handle_on_type_formatting(
     };
     let edits = match world.analysis().on_eq_typed(position) {
         None => return Ok(None),
-        Some(mut action) => action.source_file_edits.pop().unwrap().edits,
+        Some(mut action) => action
+            .source_file_edits
+            .pop()
+            .unwrap()
+            .edit
+            .as_atoms()
+            .iter()
+            .map_conv_with(&line_index)
+            .collect(),
     };
-    let edits = edits.into_iter().map_conv_with(&line_index).collect();
     Ok(Some(edits))
 }
 
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index 785877c4ba..73cccc9dd9 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -8,7 +8,7 @@ use ra_analysis::{
     Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData,
     SourceRootId
 };
-use ra_vfs::{Vfs, VfsChange, VfsFile};
+use ra_vfs::{Vfs, VfsChange, VfsFile, VfsRoot};
 use rustc_hash::FxHashMap;
 use relative_path::RelativePathBuf;
 use parking_lot::RwLock;
@@ -183,4 +183,12 @@ impl ServerWorld {
             .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
         Ok(url)
     }
+
+    pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> {
+        let base = self.vfs.read().root2path(VfsRoot(root.0));
+        let path = path.to_path(base);
+        let url = Url::from_file_path(&path)
+            .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
+        Ok(url)
+    }
 }
diff --git a/crates/ra_text_edit/src/text_edit.rs b/crates/ra_text_edit/src/text_edit.rs
index fb46f046d8..392968d638 100644
--- a/crates/ra_text_edit/src/text_edit.rs
+++ b/crates/ra_text_edit/src/text_edit.rs
@@ -41,8 +41,8 @@ impl TextEditBuilder {
 }
 
 impl TextEdit {
-    pub fn into_atoms(self) -> Vec<AtomTextEdit> {
-        self.atoms
+    pub fn as_atoms(&self) -> &[AtomTextEdit] {
+        &self.atoms
     }
 
     pub fn apply(&self, text: &str) -> String {


Test patch:
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs
index 889b568b9a..67738da48f 100644
--- a/crates/ra_analysis/tests/tests.rs
+++ b/crates/ra_analysis/tests/tests.rs
@@ -81,7 +81,7 @@ fn test_unresolved_module_diagnostic() {
             fix: Some(SourceChange {
                 label: "create module",
                 source_file_edits: [],
-                file_system_edits: [CreateFile { anchor: FileId(1), path: "../foo.rs" }],
+                file_system_edits: [CreateFile { source_root: SourceRootId(0), path: "foo.rs" }],
                 cursor_position: None }) }]"#,
         &diagnostics,
     );