This repository has been archived by the owner on Dec 29, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 255
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The only code lens we provide atm is "run a single test"
- Loading branch information
Showing
14 changed files
with
271 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
use actions::InitActionContext; | ||
use ordslice::Ext; | ||
use regex::Regex; | ||
use span::{Column, Position, Range, Row, ZeroIndexed}; | ||
use vfs::FileContents; | ||
|
||
use std::{collections::HashMap, iter, path::Path}; | ||
|
||
pub fn collect_run_actions(ctx: &InitActionContext, file: &Path) -> Vec<RunAction> { | ||
let text = match ctx.vfs.load_file(file) { | ||
Ok(FileContents::Text(text)) => text, | ||
Ok(FileContents::Binary(_)) => return Vec::new(), | ||
Err(e) => { | ||
error!("failed to collect run actions: {}", e); | ||
return Vec::new(); | ||
} | ||
}; | ||
if !text.contains("#[test]") { | ||
return Vec::new(); | ||
} | ||
|
||
lazy_static! { | ||
static ref TEST_FN_RE: Regex = Regex::new(r"#\[test\]\s*\n\s*fn\s*(?P<name>\w+)\(").unwrap(); | ||
} | ||
|
||
let line_index = LineIndex::new(&text); | ||
|
||
let mut ret = Vec::new(); | ||
for caps in TEST_FN_RE.captures_iter(&text) { | ||
let group = caps.name("name").unwrap(); | ||
let target_element = Range::from_positions( | ||
line_index.offset_to_position(group.start()), | ||
line_index.offset_to_position(group.end()), | ||
); | ||
let test_name = group.as_str(); | ||
let run_action = RunAction { | ||
label: "Run test".to_string(), | ||
target_element, | ||
cmd: Cmd { | ||
binary: "cargo".to_string(), | ||
args: vec![ | ||
"test".to_string(), | ||
"--".to_string(), | ||
"--nocapture".to_string(), | ||
test_name.to_string(), | ||
], | ||
env: iter::once(("RUST_BACKTRACE".to_string(), "short".to_string())).collect(), | ||
}, | ||
}; | ||
ret.push(run_action); | ||
} | ||
ret | ||
} | ||
|
||
pub struct RunAction { | ||
pub label: String, | ||
pub target_element: Range<ZeroIndexed>, | ||
pub cmd: Cmd, | ||
} | ||
|
||
#[derive(Serialize)] | ||
pub struct Cmd { | ||
pub binary: String, | ||
pub args: Vec<String>, | ||
pub env: HashMap<String, String>, | ||
} | ||
|
||
pub struct LineIndex { | ||
newlines: Vec<usize>, | ||
} | ||
|
||
impl LineIndex { | ||
pub fn new(text: &str) -> LineIndex { | ||
let newlines = text | ||
.bytes() | ||
.enumerate() | ||
.filter(|&(_i, b)| b == b'\n') | ||
.map(|(i, _b)| i + 1); | ||
let newlines = iter::once(0).chain(newlines).collect(); | ||
LineIndex { newlines } | ||
} | ||
|
||
pub fn offset_to_position(&self, offset: usize) -> Position<ZeroIndexed> { | ||
let line = self.newlines.upper_bound(&offset) - 1; | ||
let line_start_offset = self.newlines[line]; | ||
let col = offset - line_start_offset; | ||
Position::new( | ||
Row::new_zero_indexed(line as u32), | ||
Column::new_zero_indexed(col as u32), | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
use std::{ | ||
path::Path, | ||
}; | ||
|
||
use url::Url; | ||
use serde_json; | ||
use ls_types::{ | ||
TextDocumentIdentifier, CodeLensParams | ||
}; | ||
|
||
use ::{ | ||
server as ls_server, | ||
actions::requests, | ||
}; | ||
use super::{ | ||
Environment, expect_messages, request, ExpectedMessage, initialize | ||
}; | ||
|
||
#[test] | ||
fn test_lens_run() { | ||
let mut env = Environment::new("lens_run"); | ||
|
||
let source_file_path = Path::new("src").join("main.rs"); | ||
|
||
let root_path = env.cache.abs_path(Path::new(".")); | ||
let url = Url::from_file_path(env.cache.abs_path(&source_file_path)) | ||
.expect("couldn't convert file path to URL"); | ||
let text_doc = TextDocumentIdentifier::new(url.clone()); | ||
let messages = vec![ | ||
initialize(0, root_path.as_os_str().to_str().map(|x| x.to_owned())).to_string(), | ||
request::<requests::CodeLensRequest>( | ||
100, | ||
CodeLensParams { | ||
text_document: text_doc.clone(), | ||
}, | ||
).to_string(), | ||
]; | ||
|
||
let (mut server, results) = env.mock_server(messages); | ||
// Initialize and build. | ||
assert_eq!( | ||
ls_server::LsService::handle_message(&mut server), | ||
ls_server::ServerStateChange::Continue | ||
); | ||
expect_messages( | ||
results.clone(), | ||
&[ | ||
ExpectedMessage::new(Some(0)).expect_contains("rls.deglobImports-"), | ||
ExpectedMessage::new(None).expect_contains("progress"), | ||
ExpectedMessage::new(None).expect_contains("progress"), | ||
ExpectedMessage::new(None).expect_contains("progress"), | ||
ExpectedMessage::new(None).expect_contains("progress"), | ||
ExpectedMessage::new(None).expect_contains("progress"), | ||
], | ||
); | ||
|
||
assert_eq!( | ||
ls_server::LsService::handle_message(&mut server), | ||
ls_server::ServerStateChange::Continue | ||
); | ||
wait_for_n_results!(1, results); | ||
let result: serde_json::Value = serde_json::from_str(&results.lock().unwrap().remove(0)).unwrap(); | ||
compare_json( | ||
result.get("result").unwrap(), | ||
r#"[{ | ||
"command": { | ||
"command": "rls.run", | ||
"title": "Run test", | ||
"arguments": [{ | ||
"args": [ "test", "--", "--nocapture", "test_foo" ], | ||
"binary": "cargo", | ||
"env": { "RUST_BACKTRACE": "short" } | ||
}] | ||
}, | ||
"range": { | ||
"start": { "character": 3, "line": 14 }, | ||
"end": { "character": 11, "line": 14 } | ||
} | ||
}]"# | ||
) | ||
} | ||
|
||
fn compare_json(actual: &serde_json::Value, expected: &str) { | ||
let expected: serde_json::Value = serde_json::from_str(expected).unwrap(); | ||
if actual != &expected { | ||
panic!( | ||
"JSON differs\nExpected:\n{}\nActual:\n{}\n", | ||
serde_json::to_string_pretty(&expected).unwrap(), | ||
serde_json::to_string_pretty(actual).unwrap(), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[package] | ||
name = "run" | ||
version = "0.1.0" | ||
authors = ["Nick Cameron <[email protected]>"] | ||
|
||
[dependencies] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
pub fn main() { | ||
} | ||
|
||
#[test] | ||
fn test_foo() { | ||
|
||
} |