diff options
Diffstat (limited to 'crates/server/src')
-rw-r--r-- | crates/server/src/main.rs | 1 | ||||
-rw-r--r-- | crates/server/src/main_loop/handlers.rs | 52 | ||||
-rw-r--r-- | crates/server/src/path_map.rs | 23 | ||||
-rw-r--r-- | crates/server/src/server_world.rs | 5 |
4 files changed, 56 insertions, 25 deletions
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; | |||
18 | extern crate libanalysis; | 18 | extern crate libanalysis; |
19 | extern crate libsyntax2; | 19 | extern crate libsyntax2; |
20 | extern crate im; | 20 | extern crate im; |
21 | extern crate relative_path; | ||
21 | 22 | ||
22 | mod io; | 23 | mod io; |
23 | mod caps; | 24 | 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::{ | |||
7 | CompletionItem, | 7 | CompletionItem, |
8 | }; | 8 | }; |
9 | use serde_json::{to_value, from_value}; | 9 | use serde_json::{to_value, from_value}; |
10 | use libanalysis::{Query, QuickFix, FileId}; | 10 | use url_serde; |
11 | use libanalysis::{self, Query, FileId}; | ||
11 | use libeditor; | 12 | use libeditor; |
12 | use libsyntax2::{ | 13 | use libsyntax2::{ |
13 | TextUnit, | 14 | TextUnit, |
@@ -144,24 +145,49 @@ pub fn handle_code_action( | |||
144 | if !contains_offset_nonstrict(diag.range, offset) { | 145 | if !contains_offset_nonstrict(diag.range, offset) { |
145 | continue; | 146 | continue; |
146 | } | 147 | } |
147 | let cmd = match quick_fix { | 148 | let mut ops = Vec::new(); |
148 | QuickFix::CreateFile(path) => { | 149 | for op in quick_fix.fs_ops { |
149 | let path = &path.to_str().unwrap()[3..]; // strip `../` b/c url is weird | 150 | let op = match op { |
150 | let uri = params.text_document.uri.join(path) | 151 | libanalysis::FsOp::CreateFile { anchor, path } => { |
151 | .unwrap(); | 152 | let uri = world.file_id_to_uri(anchor)?; |
152 | let uri = ::url_serde::Ser::new(&uri); | 153 | let path = &path.as_str()[3..]; // strip `../` b/c url is weird |
153 | Command { | 154 | let uri = uri.join(path)?; |
154 | title: "Create file".to_string(), | 155 | FsOp::CreateFile { uri } |
155 | command: "libsyntax-rust.createFile".to_string(), | 156 | }, |
156 | arguments: Some(vec![to_value(uri).unwrap()]), | 157 | libanalysis::FsOp::MoveFile { file, path } => { |
157 | } | 158 | let src = world.file_id_to_uri(file)?; |
158 | } | 159 | let path = &path.as_str()[3..]; // strip `../` b/c url is weird |
160 | let dst = src.join(path)?; | ||
161 | FsOp::MoveFile { src, dst } | ||
162 | }, | ||
163 | }; | ||
164 | ops.push(op) | ||
165 | } | ||
166 | let cmd = Command { | ||
167 | title: "Create module".to_string(), | ||
168 | command: "libsyntax-rust.fsEdit".to_string(), | ||
169 | arguments: Some(vec![to_value(ops).unwrap()]), | ||
159 | }; | 170 | }; |
160 | res.push(cmd) | 171 | res.push(cmd) |
161 | } | 172 | } |
162 | return Ok(Some(res)); | 173 | return Ok(Some(res)); |
163 | } | 174 | } |
164 | 175 | ||
176 | #[derive(Serialize)] | ||
177 | #[serde(tag = "type", rename_all = "camelCase")] | ||
178 | enum FsOp { | ||
179 | CreateFile { | ||
180 | #[serde(with = "url_serde")] | ||
181 | uri: Url | ||
182 | }, | ||
183 | MoveFile { | ||
184 | #[serde(with = "url_serde")] | ||
185 | src: Url, | ||
186 | #[serde(with = "url_serde")] | ||
187 | dst: Url, | ||
188 | } | ||
189 | } | ||
190 | |||
165 | pub fn handle_runnables( | 191 | pub fn handle_runnables( |
166 | world: ServerWorld, | 192 | world: ServerWorld, |
167 | params: req::RunnablesParams, | 193 | 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 @@ | |||
1 | use std::path::{PathBuf, Path, Component}; | 1 | use std::path::{PathBuf, Path, Component}; |
2 | use im; | 2 | use im; |
3 | use libanalysis::{FileId}; | 3 | use relative_path::RelativePath; |
4 | use libanalysis::{FileId, FileResolver}; | ||
4 | 5 | ||
5 | #[derive(Debug, Default, Clone)] | 6 | #[derive(Debug, Default, Clone)] |
6 | pub struct PathMap { | 7 | pub struct PathMap { |
@@ -34,12 +35,6 @@ impl PathMap { | |||
34 | .as_path() | 35 | .as_path() |
35 | } | 36 | } |
36 | 37 | ||
37 | pub fn resolve(&self, id: FileId, relpath: &Path) -> Option<FileId> { | ||
38 | let path = self.get_path(id).join(relpath); | ||
39 | let path = normalize(&path); | ||
40 | self.get_id(&path) | ||
41 | } | ||
42 | |||
43 | fn insert(&mut self, path: PathBuf, id: FileId) { | 38 | fn insert(&mut self, path: PathBuf, id: FileId) { |
44 | self.path2id.insert(path.clone(), id); | 39 | self.path2id.insert(path.clone(), id); |
45 | self.id2path.insert(id, path.clone()); | 40 | self.id2path.insert(id, path.clone()); |
@@ -52,6 +47,18 @@ impl PathMap { | |||
52 | } | 47 | } |
53 | } | 48 | } |
54 | 49 | ||
50 | impl FileResolver for PathMap { | ||
51 | fn file_stem(&self, id: FileId) -> String { | ||
52 | self.get_path(id).file_stem().unwrap().to_str().unwrap().to_string() | ||
53 | } | ||
54 | |||
55 | fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId> { | ||
56 | let path = path.to_path(&self.get_path(id)); | ||
57 | let path = normalize(&path); | ||
58 | self.get_id(&path) | ||
59 | } | ||
60 | } | ||
61 | |||
55 | fn normalize(path: &Path) -> PathBuf { | 62 | fn normalize(path: &Path) -> PathBuf { |
56 | let mut components = path.components().peekable(); | 63 | let mut components = path.components().peekable(); |
57 | let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { | 64 | let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { |
@@ -89,7 +96,7 @@ mod test { | |||
89 | let id1 = m.get_or_insert(PathBuf::from("/foo")); | 96 | let id1 = m.get_or_insert(PathBuf::from("/foo")); |
90 | let id2 = m.get_or_insert(PathBuf::from("/foo/bar.rs")); | 97 | let id2 = m.get_or_insert(PathBuf::from("/foo/bar.rs")); |
91 | assert_eq!( | 98 | assert_eq!( |
92 | m.resolve(id1, &PathBuf::from("bar.rs")), | 99 | m.resolve(id1, &RelativePath::new("bar.rs")), |
93 | Some(id2), | 100 | Some(id2), |
94 | ) | 101 | ) |
95 | } | 102 | } |
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 { | |||
87 | } | 87 | } |
88 | 88 | ||
89 | pub fn snapshot(&self) -> ServerWorld { | 89 | pub fn snapshot(&self) -> ServerWorld { |
90 | let pm = self.path_map.clone(); | ||
91 | ServerWorld { | 90 | ServerWorld { |
92 | analysis: self.analysis.snapshot(move |id, path| { | 91 | analysis: self.analysis.snapshot(self.path_map.clone()), |
93 | pm.resolve(id, path) | ||
94 | }), | ||
95 | path_map: self.path_map.clone() | 92 | path_map: self.path_map.clone() |
96 | } | 93 | } |
97 | } | 94 | } |