aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/main_loop
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src/main_loop')
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs111
1 files changed, 65 insertions, 46 deletions
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index fa7179cd8..9d7f4f9f1 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -268,41 +268,29 @@ pub fn handle_runnables(
268 }; 268 };
269 res.push(r); 269 res.push(r);
270 } 270 }
271 let mut check_args = vec!["check".to_string()];
272 match CargoTargetSpec::for_file(&world, file_id)? {
273 Some(spec) => spec.push_to(&mut check_args),
274 None => check_args.push("--all".to_string()),
275 }
271 // Always add `cargo check`. 276 // Always add `cargo check`.
272 res.push(req::Runnable { 277 res.push(req::Runnable {
273 range: Default::default(), 278 range: Default::default(),
274 label: "cargo check".to_string(), 279 label: "cargo check".to_string(),
275 bin: "cargo".to_string(), 280 bin: "cargo".to_string(),
276 args: vec!["check".to_string(), "--all".to_string()], 281 args: check_args,
277 env: FxHashMap::default(), 282 env: FxHashMap::default(),
278 }); 283 });
279 return Ok(res); 284 return Ok(res);
280 285
281 fn runnable_args(world: &ServerWorld, file_id: FileId, kind: &RunnableKind) -> Result<Vec<String>> { 286 fn runnable_args(world: &ServerWorld, file_id: FileId, kind: &RunnableKind) -> Result<Vec<String>> {
282 let spec = if let Some(&crate_id) = world.analysis().crate_for(file_id)?.first() { 287 let spec = CargoTargetSpec::for_file(world, file_id)?;
283 let file_id = world.analysis().crate_root(crate_id)?;
284 let path = world.path_map.get_path(file_id);
285 world
286 .workspaces
287 .iter()
288 .filter_map(|ws| {
289 let tgt = ws.target_by_root(path)?;
290 Some((
291 tgt.package(ws).name(ws),
292 tgt.name(ws),
293 tgt.kind(ws),
294 ))
295 })
296 .next()
297 } else {
298 None
299 };
300 let mut res = Vec::new(); 288 let mut res = Vec::new();
301 match kind { 289 match kind {
302 RunnableKind::Test { name } => { 290 RunnableKind::Test { name } => {
303 res.push("test".to_string()); 291 res.push("test".to_string());
304 if let Some((pkg_name, tgt_name, tgt_kind)) = spec { 292 if let Some(spec) = spec {
305 spec_args(pkg_name, tgt_name, tgt_kind, &mut res); 293 spec.push_to(&mut res);
306 } 294 }
307 res.push("--".to_string()); 295 res.push("--".to_string());
308 res.push(name.to_string()); 296 res.push(name.to_string());
@@ -310,38 +298,69 @@ pub fn handle_runnables(
310 } 298 }
311 RunnableKind::Bin => { 299 RunnableKind::Bin => {
312 res.push("run".to_string()); 300 res.push("run".to_string());
313 if let Some((pkg_name, tgt_name, tgt_kind)) = spec { 301 if let Some(spec) = spec {
314 spec_args(pkg_name, tgt_name, tgt_kind, &mut res); 302 spec.push_to(&mut res);
315 } 303 }
316 } 304 }
317 } 305 }
318 Ok(res) 306 Ok(res)
319 } 307 }
320 308
321 fn spec_args(pkg_name: &str, tgt_name: &str, tgt_kind: TargetKind, buf: &mut Vec<String>) { 309 struct CargoTargetSpec {
322 buf.push("--package".to_string()); 310 package: String,
323 buf.push(pkg_name.to_string()); 311 target: String,
324 match tgt_kind { 312 target_kind: TargetKind,
325 TargetKind::Bin => { 313 }
326 buf.push("--bin".to_string()); 314
327 buf.push(tgt_name.to_string()); 315 impl CargoTargetSpec {
328 } 316 fn for_file(world: &ServerWorld, file_id: FileId) -> Result<Option<CargoTargetSpec>> {
329 TargetKind::Test => { 317 let &crate_id = match world.analysis().crate_for(file_id)?.first() {
330 buf.push("--test".to_string()); 318 Some(crate_id) => crate_id,
331 buf.push(tgt_name.to_string()); 319 None => return Ok(None),
332 } 320 };
333 TargetKind::Bench => { 321 let file_id = world.analysis().crate_root(crate_id)?;
334 buf.push("--bench".to_string()); 322 let path = world.path_map.get_path(file_id);
335 buf.push(tgt_name.to_string()); 323 let res = world
336 } 324 .workspaces
337 TargetKind::Example => { 325 .iter()
338 buf.push("--example".to_string()); 326 .find_map(|ws| {
339 buf.push(tgt_name.to_string()); 327 let tgt = ws.target_by_root(path)?;
340 } 328 let res = CargoTargetSpec {
341 TargetKind::Lib => { 329 package: tgt.package(ws).name(ws).to_string(),
342 buf.push("--lib".to_string()); 330 target: tgt.name(ws).to_string(),
331 target_kind: tgt.kind(ws),
332 };
333 Some(res)
334 });
335 Ok(res)
336 }
337
338 fn push_to(self, buf: &mut Vec<String>) {
339 buf.push("--package".to_string());
340 buf.push(self.package);
341 match self.target_kind {
342 TargetKind::Bin => {
343 buf.push("--bin".to_string());
344 buf.push(self.target);
345 }
346 TargetKind::Test => {
347 buf.push("--test".to_string());
348 buf.push(self.target);
349 }
350 TargetKind::Bench => {
351 buf.push("--bench".to_string());
352 buf.push(self.target);
353 }
354 TargetKind::Example => {
355 buf.push("--example".to_string());
356 buf.push(self.target);
357 }
358 TargetKind::Lib => {
359 buf.push("--lib".to_string());
360 }
361 TargetKind::Other => (),
343 } 362 }
344 TargetKind::Other => (), 363
345 } 364 }
346 } 365 }
347} 366}