From d34588bf83898870d7f9b4b49ac2a5f71c77dabb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 28 Aug 2018 18:22:52 +0300 Subject: create module smartly --- crates/server/src/main.rs | 1 + crates/server/src/main_loop/handlers.rs | 52 ++++++++++++++++++++++++--------- crates/server/src/path_map.rs | 23 ++++++++++----- crates/server/src/server_world.rs | 5 +--- 4 files changed, 56 insertions(+), 25 deletions(-) (limited to 'crates/server/src') diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 615dd082c..1a93af65b 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -18,6 +18,7 @@ extern crate libeditor; extern crate libanalysis; extern crate libsyntax2; extern crate im; +extern crate relative_path; mod io; mod caps; diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs index ca5cd5ab1..92ffb30c3 100644 --- a/crates/server/src/main_loop/handlers.rs +++ b/crates/server/src/main_loop/handlers.rs @@ -7,7 +7,8 @@ use languageserver_types::{ CompletionItem, }; use serde_json::{to_value, from_value}; -use libanalysis::{Query, QuickFix, FileId}; +use url_serde; +use libanalysis::{self, Query, FileId}; use libeditor; use libsyntax2::{ TextUnit, @@ -144,24 +145,49 @@ pub fn handle_code_action( if !contains_offset_nonstrict(diag.range, offset) { continue; } - let cmd = match quick_fix { - QuickFix::CreateFile(path) => { - let path = &path.to_str().unwrap()[3..]; // strip `../` b/c url is weird - let uri = params.text_document.uri.join(path) - .unwrap(); - let uri = ::url_serde::Ser::new(&uri); - Command { - title: "Create file".to_string(), - command: "libsyntax-rust.createFile".to_string(), - arguments: Some(vec![to_value(uri).unwrap()]), - } - } + let mut ops = Vec::new(); + for op in quick_fix.fs_ops { + let op = match op { + libanalysis::FsOp::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)?; + FsOp::CreateFile { uri } + }, + libanalysis::FsOp::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)?; + FsOp::MoveFile { src, dst } + }, + }; + ops.push(op) + } + let cmd = Command { + title: "Create module".to_string(), + command: "libsyntax-rust.fsEdit".to_string(), + arguments: Some(vec![to_value(ops).unwrap()]), }; res.push(cmd) } return Ok(Some(res)); } +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +enum FsOp { + CreateFile { + #[serde(with = "url_serde")] + uri: Url + }, + MoveFile { + #[serde(with = "url_serde")] + src: Url, + #[serde(with = "url_serde")] + dst: Url, + } +} + pub fn handle_runnables( world: ServerWorld, params: req::RunnablesParams, diff --git a/crates/server/src/path_map.rs b/crates/server/src/path_map.rs index d2b811a3b..f4ac47e70 100644 --- a/crates/server/src/path_map.rs +++ b/crates/server/src/path_map.rs @@ -1,6 +1,7 @@ use std::path::{PathBuf, Path, Component}; use im; -use libanalysis::{FileId}; +use relative_path::RelativePath; +use libanalysis::{FileId, FileResolver}; #[derive(Debug, Default, Clone)] pub struct PathMap { @@ -34,12 +35,6 @@ impl PathMap { .as_path() } - pub fn resolve(&self, id: FileId, relpath: &Path) -> Option { - let path = self.get_path(id).join(relpath); - let path = normalize(&path); - self.get_id(&path) - } - fn insert(&mut self, path: PathBuf, id: FileId) { self.path2id.insert(path.clone(), id); self.id2path.insert(id, path.clone()); @@ -52,6 +47,18 @@ impl PathMap { } } +impl FileResolver for PathMap { + fn file_stem(&self, id: FileId) -> String { + self.get_path(id).file_stem().unwrap().to_str().unwrap().to_string() + } + + fn resolve(&self, id: FileId, path: &RelativePath) -> Option { + let path = path.to_path(&self.get_path(id)); + let path = normalize(&path); + self.get_id(&path) + } +} + fn normalize(path: &Path) -> PathBuf { let mut components = path.components().peekable(); let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { @@ -89,7 +96,7 @@ mod test { let id1 = m.get_or_insert(PathBuf::from("/foo")); let id2 = m.get_or_insert(PathBuf::from("/foo/bar.rs")); assert_eq!( - m.resolve(id1, &PathBuf::from("bar.rs")), + m.resolve(id1, &RelativePath::new("bar.rs")), Some(id2), ) } diff --git a/crates/server/src/server_world.rs b/crates/server/src/server_world.rs index c0d2efb86..1593cd59f 100644 --- a/crates/server/src/server_world.rs +++ b/crates/server/src/server_world.rs @@ -87,11 +87,8 @@ impl ServerWorldState { } pub fn snapshot(&self) -> ServerWorld { - let pm = self.path_map.clone(); ServerWorld { - analysis: self.analysis.snapshot(move |id, path| { - pm.resolve(id, path) - }), + analysis: self.analysis.snapshot(self.path_map.clone()), path_map: self.path_map.clone() } } -- cgit v1.2.3