aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/libanalysis/src/imp.rs6
-rw-r--r--crates/libanalysis/src/lib.rs7
-rw-r--r--crates/libanalysis/tests/tests.rs4
-rw-r--r--crates/server/src/main_loop/handlers.rs76
-rw-r--r--crates/server/src/project_model.rs4
-rw-r--r--crates/server/src/server_world.rs17
-rw-r--r--crates/server/tests/heavy_tests/main.rs40
-rw-r--r--crates/server/tests/heavy_tests/support.rs13
8 files changed, 142 insertions, 25 deletions
diff --git a/crates/libanalysis/src/imp.rs b/crates/libanalysis/src/imp.rs
index f1d72da15..b80ce1ab5 100644
--- a/crates/libanalysis/src/imp.rs
+++ b/crates/libanalysis/src/imp.rs
@@ -151,7 +151,7 @@ impl AnalysisImpl {
151 .collect() 151 .collect()
152 } 152 }
153 153
154 pub fn crate_root(&self, id: FileId) -> Vec<CrateId> { 154 pub fn crate_for(&self, id: FileId) -> Vec<CrateId> {
155 let module_map = &self.data.module_map; 155 let module_map = &self.data.module_map;
156 let crate_graph = &self.data.crate_graph; 156 let crate_graph = &self.data.crate_graph;
157 let mut res = Vec::new(); 157 let mut res = Vec::new();
@@ -177,7 +177,9 @@ impl AnalysisImpl {
177 } 177 }
178 res 178 res
179 } 179 }
180 180 pub fn crate_root(&self, crate_id: CrateId) -> FileId {
181 self.data.crate_graph.crate_roots[&crate_id]
182 }
181 pub fn approximately_resolve_symbol( 183 pub fn approximately_resolve_symbol(
182 &self, 184 &self,
183 id: FileId, 185 id: FileId,
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index 041abbb89..ba290f1e0 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -182,8 +182,11 @@ impl Analysis {
182 pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { 182 pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
183 self.imp.parent_module(file_id) 183 self.imp.parent_module(file_id)
184 } 184 }
185 pub fn crate_root(&self, file_id: FileId) -> Vec<CrateId> { 185 pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> {
186 self.imp.crate_root(file_id) 186 self.imp.crate_for(file_id)
187 }
188 pub fn crate_root(&self, crate_id: CrateId) -> FileId {
189 self.imp.crate_root(crate_id)
187 } 190 }
188 pub fn runnables(&self, file_id: FileId) -> Vec<Runnable> { 191 pub fn runnables(&self, file_id: FileId) -> Vec<Runnable> {
189 let file = self.file_syntax(file_id); 192 let file = self.file_syntax(file_id);
diff --git a/crates/libanalysis/tests/tests.rs b/crates/libanalysis/tests/tests.rs
index c098c8e8c..4fae7c313 100644
--- a/crates/libanalysis/tests/tests.rs
+++ b/crates/libanalysis/tests/tests.rs
@@ -126,7 +126,7 @@ fn test_resolve_crate_root() {
126 (1, "/lib.rs"), 126 (1, "/lib.rs"),
127 (2, "/foo.rs"), 127 (2, "/foo.rs"),
128 ])); 128 ]));
129 assert!(snap.crate_root(FileId(2)).is_empty()); 129 assert!(snap.crate_for(FileId(2)).is_empty());
130 130
131 let crate_graph = CrateGraph { 131 let crate_graph = CrateGraph {
132 crate_roots: { 132 crate_roots: {
@@ -142,7 +142,7 @@ fn test_resolve_crate_root() {
142 (2, "/foo.rs"), 142 (2, "/foo.rs"),
143 ])); 143 ]));
144 assert_eq!( 144 assert_eq!(
145 snap.crate_root(FileId(2)), 145 snap.crate_for(FileId(2)),
146 vec![CrateId(1)], 146 vec![CrateId(1)],
147 ); 147 );
148} 148}
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs
index ab8b6f799..93d8bd9fe 100644
--- a/crates/server/src/main_loop/handlers.rs
+++ b/crates/server/src/main_loop/handlers.rs
@@ -16,6 +16,7 @@ use ::{
16 req::{self, Decoration}, Result, 16 req::{self, Decoration}, Result,
17 conv::{Conv, ConvWith, TryConvWith, MapConvWith, to_location}, 17 conv::{Conv, ConvWith, TryConvWith, MapConvWith, to_location},
18 server_world::ServerWorld, 18 server_world::ServerWorld,
19 project_model::TargetKind,
19}; 20};
20 21
21pub fn handle_syntax_tree( 22pub fn handle_syntax_tree(
@@ -233,6 +234,8 @@ pub fn handle_runnables(
233 } 234 }
234 } 235 }
235 236
237 let args = runnable_args(&world, file_id, &runnable.kind);
238
236 let r = req::Runnable { 239 let r = req::Runnable {
237 range: runnable.range.conv_with(&line_index), 240 range: runnable.range.conv_with(&line_index),
238 label: match &runnable.kind { 241 label: match &runnable.kind {
@@ -242,17 +245,7 @@ pub fn handle_runnables(
242 "run binary".to_string(), 245 "run binary".to_string(),
243 }, 246 },
244 bin: "cargo".to_string(), 247 bin: "cargo".to_string(),
245 args: match runnable.kind { 248 args,
246 RunnableKind::Test { name } => {
247 vec![
248 "test".to_string(),
249 "--".to_string(),
250 name,
251 "--nocapture".to_string(),
252 ]
253 }
254 RunnableKind::Bin => vec!["run".to_string()]
255 },
256 env: { 249 env: {
257 let mut m = HashMap::new(); 250 let mut m = HashMap::new();
258 m.insert( 251 m.insert(
@@ -265,6 +258,67 @@ pub fn handle_runnables(
265 res.push(r); 258 res.push(r);
266 } 259 }
267 return Ok(res); 260 return Ok(res);
261
262 fn runnable_args(world: &ServerWorld, file_id: FileId, kind: &RunnableKind) -> Vec<String> {
263 let spec = if let Some(&crate_id) = world.analysis().crate_for(file_id).first() {
264 let file_id = world.analysis().crate_root(crate_id);
265 let path = world.path_map.get_path(file_id);
266 world.workspaces.iter()
267 .filter_map(|ws| {
268 let tgt = ws.target_by_root(path)?;
269 Some((tgt.package(ws).name(ws).clone(), tgt.name(ws).clone(), tgt.kind(ws)))
270 })
271 .next()
272 } else {
273 None
274 };
275 let mut res = Vec::new();
276 match kind {
277 RunnableKind::Test { name } => {
278 res.push("test".to_string());
279 if let Some((pkg_name, tgt_name, tgt_kind)) = spec {
280 spec_args(pkg_name, tgt_name, tgt_kind, &mut res);
281 }
282 res.push("--".to_string());
283 res.push(name.to_string());
284 res.push("--nocapture".to_string());
285 }
286 RunnableKind::Bin => {
287 res.push("run".to_string());
288 if let Some((pkg_name, tgt_name, tgt_kind)) = spec {
289 spec_args(pkg_name, tgt_name, tgt_kind, &mut res);
290 }
291 }
292 }
293 res
294 }
295
296 fn spec_args(pkg_name: &str, tgt_name: &str, tgt_kind: TargetKind, buf: &mut Vec<String>) {
297 buf.push("--package".to_string());
298 buf.push(pkg_name.to_string());
299 match tgt_kind {
300 TargetKind::Bin => {
301 buf.push("--bin".to_string());
302 buf.push(tgt_name.to_string());
303 }
304 TargetKind::Test => {
305 buf.push("--test".to_string());
306 buf.push(tgt_name.to_string());
307 }
308 TargetKind::Bench => {
309 buf.push("--bench".to_string());
310 buf.push(tgt_name.to_string());
311 }
312 TargetKind::Example => {
313 buf.push("--example".to_string());
314 buf.push(tgt_name.to_string());
315 }
316 TargetKind::Lib => {
317 buf.push("--lib".to_string());
318 }
319 TargetKind::Other => (),
320 }
321 }
268} 322}
269 323
270pub fn handle_decorations( 324pub fn handle_decorations(
diff --git a/crates/server/src/project_model.rs b/crates/server/src/project_model.rs
index 1c5954dad..12233f258 100644
--- a/crates/server/src/project_model.rs
+++ b/crates/server/src/project_model.rs
@@ -56,7 +56,7 @@ impl Package {
56} 56}
57 57
58impl Target { 58impl Target {
59 pub fn pkg(self, ws: &CargoWorkspace) -> Package { 59 pub fn package(self, ws: &CargoWorkspace) -> Package {
60 ws.tgt(self).pkg 60 ws.tgt(self).pkg
61 } 61 }
62 pub fn name(self, ws: &CargoWorkspace) -> &str { 62 pub fn name(self, ws: &CargoWorkspace) -> &str {
@@ -114,7 +114,7 @@ impl CargoWorkspace {
114 pub fn ws_members<'a>(&'a self) -> impl Iterator<Item=Package> + 'a { 114 pub fn ws_members<'a>(&'a self) -> impl Iterator<Item=Package> + 'a {
115 self.ws_members.iter().cloned() 115 self.ws_members.iter().cloned()
116 } 116 }
117 pub fn target_by_roo(&self, root: &Path) -> Option<Target> { 117 pub fn target_by_root(&self, root: &Path) -> Option<Target> {
118 self.packages() 118 self.packages()
119 .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)) 119 .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root))
120 .next() 120 .next()
diff --git a/crates/server/src/server_world.rs b/crates/server/src/server_world.rs
index 4d5c50428..f78b56cf8 100644
--- a/crates/server/src/server_world.rs
+++ b/crates/server/src/server_world.rs
@@ -6,7 +6,7 @@ use std::{
6}; 6};
7 7
8use languageserver_types::Url; 8use languageserver_types::Url;
9use libanalysis::{FileId, AnalysisHost, Analysis}; 9use libanalysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId};
10 10
11use { 11use {
12 Result, 12 Result,
@@ -95,7 +95,22 @@ impl ServerWorldState {
95 Ok(file_id) 95 Ok(file_id)
96 } 96 }
97 pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { 97 pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) {
98 let mut crate_roots = HashMap::new();
99 ws.iter()
100 .flat_map(|ws| {
101 ws.packages()
102 .flat_map(move |pkg| pkg.targets(ws))
103 .map(move |tgt| tgt.root(ws))
104 })
105 .for_each(|root| {
106 if let Some(file_id) = self.path_map.get_id(root) {
107 let crate_id = CrateId(crate_roots.len() as u32);
108 crate_roots.insert(crate_id, file_id);
109 }
110 });
111 let crate_graph = CrateGraph { crate_roots };
98 self.workspaces = Arc::new(ws); 112 self.workspaces = Arc::new(ws);
113 self.analysis_host.set_crate_graph(crate_graph);
99 } 114 }
100 pub fn snapshot(&self) -> ServerWorld { 115 pub fn snapshot(&self) -> ServerWorld {
101 ServerWorld { 116 ServerWorld {
diff --git a/crates/server/tests/heavy_tests/main.rs b/crates/server/tests/heavy_tests/main.rs
index 9c0196f22..0dc6074b2 100644
--- a/crates/server/tests/heavy_tests/main.rs
+++ b/crates/server/tests/heavy_tests/main.rs
@@ -14,10 +14,10 @@ use m::req::{Runnables, RunnablesParams, DidReloadWorkspace};
14 14
15use support::project; 15use support::project;
16 16
17const LOG: &'static str = "WARN"; 17const LOG: &'static str = "";
18 18
19#[test] 19#[test]
20fn test_runnables() { 20fn test_runnables_no_project() {
21 let server = project(r" 21 let server = project(r"
22//- lib.rs 22//- lib.rs
23#[test] 23#[test]
@@ -45,6 +45,42 @@ fn foo() {
45} 45}
46 46
47#[test] 47#[test]
48fn test_runnables_project() {
49 let server = project(r#"
50//- Cargo.toml
51[package]
52name = "foo"
53version = "0.0.0"
54
55//- src/lib.rs
56pub fn foo() {}
57
58//- tests/spam.rs
59#[test]
60fn test_eggs() {}
61"#);
62 server.wait_for_notification::<DidReloadWorkspace>();
63 server.request::<Runnables>(
64 RunnablesParams {
65 text_document: server.doc_id("tests/spam.rs"),
66 position: None,
67 },
68 r#"[
69 {
70 "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--nocapture" ],
71 "bin": "cargo",
72 "env": { "RUST_BACKTRACE": "short" },
73 "label": "test test_eggs",
74 "range": {
75 "end": { "character": 17, "line": 1 },
76 "start": { "character": 0, "line": 0 }
77 }
78 }
79 ]"#
80 );
81}
82
83#[test]
48fn test_project_model() { 84fn test_project_model() {
49 let server = project(r#" 85 let server = project(r#"
50//- Cargo.toml 86//- Cargo.toml
diff --git a/crates/server/tests/heavy_tests/support.rs b/crates/server/tests/heavy_tests/support.rs
index 76cbd56ea..38a9e6c76 100644
--- a/crates/server/tests/heavy_tests/support.rs
+++ b/crates/server/tests/heavy_tests/support.rs
@@ -134,7 +134,7 @@ impl Server {
134 { 134 {
135 let expected = expected.replace("$PROJECT_ROOT$", &self.dir.path().display().to_string()); 135 let expected = expected.replace("$PROJECT_ROOT$", &self.dir.path().display().to_string());
136 let expected: Value = from_str(&expected).unwrap(); 136 let expected: Value = from_str(&expected).unwrap();
137 let actual = self.wait_for_notification(N::METHOD); 137 let actual = self.wait_for_notification::<N>();
138 assert_eq!( 138 assert_eq!(
139 expected, actual, 139 expected, actual,
140 "Expected:\n{}\n\ 140 "Expected:\n{}\n\
@@ -150,6 +150,11 @@ impl Server {
150 R::Params: Serialize, 150 R::Params: Serialize,
151 { 151 {
152 let r = RawRequest::new::<R>(id, &params); 152 let r = RawRequest::new::<R>(id, &params);
153 self.send_request_(r)
154 }
155 fn send_request_(&self, r: RawRequest) -> Value
156 {
157 let id = r.id;
153 self.sender.as_ref() 158 self.sender.as_ref()
154 .unwrap() 159 .unwrap()
155 .send(RawMessage::Request(r)); 160 .send(RawMessage::Request(r));
@@ -168,7 +173,10 @@ impl Server {
168 } 173 }
169 panic!("no response"); 174 panic!("no response");
170 } 175 }
171 fn wait_for_notification(&self, method: &str) -> Value { 176 pub fn wait_for_notification<N: Notification>(&self) -> Value {
177 self.wait_for_notification_(N::METHOD)
178 }
179 fn wait_for_notification_(&self, method: &str) -> Value {
172 let f = |msg: &RawMessage| match msg { 180 let f = |msg: &RawMessage| match msg {
173 RawMessage::Notification(n) if n.method == method => { 181 RawMessage::Notification(n) if n.method == method => {
174 Some(n.params.clone()) 182 Some(n.params.clone())
@@ -215,7 +223,6 @@ impl Drop for Server {
215 drop(msg); 223 drop(msg);
216 } 224 }
217 } 225 }
218 eprintln!("joining server");
219 self.server.take() 226 self.server.take()
220 .unwrap() 227 .unwrap()
221 .join().unwrap().unwrap(); 228 .join().unwrap().unwrap();