diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-12 18:56:11 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-12 18:56:11 +0000 |
commit | e56072bfa3e5af69a4c293a38de6e1350ada3573 (patch) | |
tree | c7093fca262cedfc1fce2ba7499330fbb343c702 /crates/ra_lsp_server/src/main_loop | |
parent | ee80a92ed4245f1b6e2b11127c8636b63930073d (diff) | |
parent | 5bf739c824c25867811163e05f706ff3d20bd2e6 (diff) |
Merge #500
500: Code lens support for running tests r=matklad a=kjeremy
Supports running individual and mod tests.
I feel like this kind of abuses the `Runnables` infrastructure but it works. Maybe later on down the line we should introduce a struct that is really just a tuple of binary, arguments, and environment and pass that back to the client instead. `run_single.ts` is just a paired down version of `runnables.ts` and there is duplication because I think run_single will probably change independent of runnables.
Co-authored-by: Jeremy A. Kolb <[email protected]>
Co-authored-by: Jeremy Kolb <[email protected]>
Diffstat (limited to 'crates/ra_lsp_server/src/main_loop')
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 141 |
1 files changed, 46 insertions, 95 deletions
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5ab13542c..a781df181 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -2,7 +2,7 @@ use std::collections::HashMap; | |||
2 | 2 | ||
3 | use gen_lsp_server::ErrorCode; | 3 | use gen_lsp_server::ErrorCode; |
4 | use languageserver_types::{ | 4 | use languageserver_types::{ |
5 | CodeActionResponse, Command, Diagnostic, DiagnosticSeverity, DocumentFormattingParams, | 5 | CodeActionResponse, Command, CodeLens, Diagnostic, DiagnosticSeverity, DocumentFormattingParams, |
6 | DocumentHighlight, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, | 6 | DocumentHighlight, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, |
7 | FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind, | 7 | FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind, |
8 | ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, RenameParams, | 8 | ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, RenameParams, |
@@ -17,8 +17,8 @@ use serde_json::to_value; | |||
17 | use std::io::Write; | 17 | use std::io::Write; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | cargo_target_spec::{CargoTargetSpec, runnable_args}, | ||
20 | conv::{to_location, to_location_link, Conv, ConvWith, MapConvWith, TryConvWith}, | 21 | conv::{to_location, to_location_link, Conv, ConvWith, MapConvWith, TryConvWith}, |
21 | project_model::TargetKind, | ||
22 | req::{self, Decoration}, | 22 | req::{self, Decoration}, |
23 | server_world::ServerWorld, | 23 | server_world::ServerWorld, |
24 | LspError, Result, | 24 | LspError, Result, |
@@ -291,99 +291,6 @@ pub fn handle_runnables( | |||
291 | env: FxHashMap::default(), | 291 | env: FxHashMap::default(), |
292 | }); | 292 | }); |
293 | return Ok(res); | 293 | return Ok(res); |
294 | |||
295 | fn runnable_args( | ||
296 | world: &ServerWorld, | ||
297 | file_id: FileId, | ||
298 | kind: &RunnableKind, | ||
299 | ) -> Result<Vec<String>> { | ||
300 | let spec = CargoTargetSpec::for_file(world, file_id)?; | ||
301 | let mut res = Vec::new(); | ||
302 | match kind { | ||
303 | RunnableKind::Test { name } => { | ||
304 | res.push("test".to_string()); | ||
305 | if let Some(spec) = spec { | ||
306 | spec.push_to(&mut res); | ||
307 | } | ||
308 | res.push("--".to_string()); | ||
309 | res.push(name.to_string()); | ||
310 | res.push("--nocapture".to_string()); | ||
311 | } | ||
312 | RunnableKind::TestMod { path } => { | ||
313 | res.push("test".to_string()); | ||
314 | if let Some(spec) = spec { | ||
315 | spec.push_to(&mut res); | ||
316 | } | ||
317 | res.push("--".to_string()); | ||
318 | res.push(path.to_string()); | ||
319 | res.push("--nocapture".to_string()); | ||
320 | } | ||
321 | RunnableKind::Bin => { | ||
322 | res.push("run".to_string()); | ||
323 | if let Some(spec) = spec { | ||
324 | spec.push_to(&mut res); | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | Ok(res) | ||
329 | } | ||
330 | |||
331 | struct CargoTargetSpec { | ||
332 | package: String, | ||
333 | target: String, | ||
334 | target_kind: TargetKind, | ||
335 | } | ||
336 | |||
337 | impl CargoTargetSpec { | ||
338 | fn for_file(world: &ServerWorld, file_id: FileId) -> Result<Option<CargoTargetSpec>> { | ||
339 | let &crate_id = match world.analysis().crate_for(file_id)?.first() { | ||
340 | Some(crate_id) => crate_id, | ||
341 | None => return Ok(None), | ||
342 | }; | ||
343 | let file_id = world.analysis().crate_root(crate_id)?; | ||
344 | let path = world | ||
345 | .vfs | ||
346 | .read() | ||
347 | .file2path(ra_vfs::VfsFile(file_id.0.into())); | ||
348 | let res = world.workspaces.iter().find_map(|ws| { | ||
349 | let tgt = ws.cargo.target_by_root(&path)?; | ||
350 | let res = CargoTargetSpec { | ||
351 | package: tgt.package(&ws.cargo).name(&ws.cargo).to_string(), | ||
352 | target: tgt.name(&ws.cargo).to_string(), | ||
353 | target_kind: tgt.kind(&ws.cargo), | ||
354 | }; | ||
355 | Some(res) | ||
356 | }); | ||
357 | Ok(res) | ||
358 | } | ||
359 | |||
360 | fn push_to(self, buf: &mut Vec<String>) { | ||
361 | buf.push("--package".to_string()); | ||
362 | buf.push(self.package); | ||
363 | match self.target_kind { | ||
364 | TargetKind::Bin => { | ||
365 | buf.push("--bin".to_string()); | ||
366 | buf.push(self.target); | ||
367 | } | ||
368 | TargetKind::Test => { | ||
369 | buf.push("--test".to_string()); | ||
370 | buf.push(self.target); | ||
371 | } | ||
372 | TargetKind::Bench => { | ||
373 | buf.push("--bench".to_string()); | ||
374 | buf.push(self.target); | ||
375 | } | ||
376 | TargetKind::Example => { | ||
377 | buf.push("--example".to_string()); | ||
378 | buf.push(self.target); | ||
379 | } | ||
380 | TargetKind::Lib => { | ||
381 | buf.push("--lib".to_string()); | ||
382 | } | ||
383 | TargetKind::Other => (), | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | } | 294 | } |
388 | 295 | ||
389 | pub fn handle_decorations( | 296 | pub fn handle_decorations( |
@@ -669,6 +576,50 @@ pub fn handle_code_action( | |||
669 | Ok(Some(CodeActionResponse::Commands(res))) | 576 | Ok(Some(CodeActionResponse::Commands(res))) |
670 | } | 577 | } |
671 | 578 | ||
579 | pub fn handle_code_lens( | ||
580 | world: ServerWorld, | ||
581 | params: req::CodeLensParams, | ||
582 | ) -> Result<Option<Vec<CodeLens>>> { | ||
583 | let file_id = params.text_document.try_conv_with(&world)?; | ||
584 | let line_index = world.analysis().file_line_index(file_id); | ||
585 | |||
586 | let mut lenses: Vec<CodeLens> = Default::default(); | ||
587 | |||
588 | for runnable in world.analysis().runnables(file_id)? { | ||
589 | match &runnable.kind { | ||
590 | RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => { | ||
591 | let args = runnable_args(&world, file_id, &runnable.kind)?; | ||
592 | |||
593 | let range = runnable.range.conv_with(&line_index); | ||
594 | |||
595 | // This represents the actual command that will be run. | ||
596 | let r: req::Runnable = req::Runnable { | ||
597 | range, | ||
598 | label: Default::default(), | ||
599 | bin: "cargo".into(), | ||
600 | args, | ||
601 | env: Default::default(), | ||
602 | }; | ||
603 | |||
604 | let lens = CodeLens { | ||
605 | range, | ||
606 | command: Some(Command { | ||
607 | title: "Run Test".into(), | ||
608 | command: "ra-lsp.run-single".into(), | ||
609 | arguments: Some(vec![to_value(r).unwrap()]), | ||
610 | }), | ||
611 | data: None, | ||
612 | }; | ||
613 | |||
614 | lenses.push(lens); | ||
615 | } | ||
616 | _ => continue, | ||
617 | }; | ||
618 | } | ||
619 | |||
620 | return Ok(Some(lenses)); | ||
621 | } | ||
622 | |||
672 | pub fn handle_document_highlight( | 623 | pub fn handle_document_highlight( |
673 | world: ServerWorld, | 624 | world: ServerWorld, |
674 | params: req::TextDocumentPositionParams, | 625 | params: req::TextDocumentPositionParams, |