diff --git a/Cargo.lock b/Cargo.lock index 5b2b98a00f6..81facea1e50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,8 +8,8 @@ dependencies = [ "languageserver-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.5.0", + "rls-data 0.8.0", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -647,20 +647,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rls-analysis" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.5.0" dependencies = [ "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.8.0", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rls-data" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.8.0" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1147,8 +1145,6 @@ dependencies = [ "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "78a05b130793ebc781c2d933299d7214a10d014fdebe5184eb652c81ba8d3184" -"checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" diff --git a/Cargo.toml b/Cargo.toml index 5e767d9da1c..7be4c8efee3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,10 +16,10 @@ env_logger = "0.4" languageserver-types = "0.11" log = "0.3" racer = "2.0.6" -rls-analysis = "0.4" -rls-data = "0.7" -rls-span = { version = "0.4" , features = ["serialize-serde"] } -rls-vfs = { version = "0.4", features = ["racer-impls"] } +rls-analysis = { path = "../rls-analysis" } +rls-data = { path = "../rls-data", default-features = true, features = ["borrows"] } +rls-span = { version = "0.4", features = ["serialize-serde"] } +rls-vfs = { version = "0.4.2", features = ["racer-impls"] } rustfmt-nightly = "0.1" serde = "1.0" serde_json = "1.0" diff --git a/src/actions/mod.rs b/src/actions/mod.rs index 65a092c41d1..00442f77d71 100644 --- a/src/actions/mod.rs +++ b/src/actions/mod.rs @@ -435,6 +435,35 @@ impl ActionHandler { } } + pub fn borrow_info(&self, id: usize, params: TextDocumentPositionParams, out: O) { + let t = thread::current(); + let span = self.convert_pos_to_span(¶ms.text_document, params.position); + + trace!("borrow_info: {:?}", span); + + let analysis = self.analysis.clone(); + let rustw_handle = thread::spawn(move || { + let bi = analysis.borrow_info(&span); + t.unpark(); + bi.map(|b| b.into()) + }); + + thread::park_timeout(Duration::from_millis(::COMPILER_TIMEOUT)); + + let result = rustw_handle.join(); + match result { + Ok(Ok(r)) => { + out.success(id, ResponseData::BorrowInfo(r)); + }, + Ok(Err(e)) => { + out.failure(id, &format!("BorrowInfo not available for that location: {:?}", e)[..]); + } + Err(_) => { + out.failure(id, "BorrowInfo failed to complete successfully"); + } + } + } + pub fn execute_command(&self, id: usize, params: ExecuteCommandParams, out: O) { match &*params.command { "rls.applySuggestion" => { diff --git a/src/build.rs b/src/build.rs index 6535b959d39..989e19c047d 100644 --- a/src/build.rs +++ b/src/build.rs @@ -570,6 +570,7 @@ impl BuildQueue { let analysis = self.analysis.clone(); result.after_analysis.callback = Box::new(move |state| { + let borrow_analysis = state.borrow_analysis_map.take().unwrap(); // There are two ways to move the data from rustc to the RLS, either // directly or by serialising and deserialising. We only want to do // the latter when there are compatibility issues between crates. @@ -578,6 +579,7 @@ impl BuildQueue { // save::process_crate(state.tcx.unwrap(), // state.expanded_crate.unwrap(), // state.analysis.unwrap(), + // borrow_analysis, // state.crate_name.unwrap(), // save::DumpHandler::new(save::Format::Json, // state.out_dir, @@ -586,6 +588,7 @@ impl BuildQueue { save::process_crate(state.tcx.unwrap(), state.expanded_crate.unwrap(), state.analysis.unwrap(), + borrow_analysis, state.crate_name.unwrap(), CallbackHandler { callback: &mut |a| { diff --git a/src/cmd.rs b/src/cmd.rs index 3a114957c8e..4be1766cdfe 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -76,6 +76,12 @@ pub fn run() { let col = bits.next().expect("Expected column number"); hover(file_name, row, col) } + "borrows" => { + let file_name = bits.next().expect("Expected file name"); + let row = bits.next().expect("Expected line number"); + let col = bits.next().expect("Expected column number"); + borrow_info(file_name, row, col) + } "h" | "help" => { help(); continue; @@ -127,6 +133,19 @@ fn rename(file_name: &str, row: &str, col: &str, new_name: &str) -> ServerMessag ServerMessage::Request(request) } +fn borrow_info(file_name: &str, row: &str, col: &str) -> ServerMessage { + let params = TextDocumentPositionParams { + text_document: TextDocumentIdentifier::new(url(file_name)), + position: Position::new(u64::from_str(row).expect("Bad line number"), + u64::from_str(col).expect("Bad column number")), + }; + let request = Request { + id: next_id(), + method: Method::BorrowInfo(params), + }; + ServerMessage::Request(request) +} + fn hover(file_name: &str, row: &str, col: &str) -> ServerMessage { let params = TextDocumentPositionParams { text_document: TextDocumentIdentifier::new(url(file_name)), @@ -258,4 +277,8 @@ fn help() { println!(" hover file_name line_number column_number"); println!(" textDocument/hover"); println!(" used for 'hover'"); + println!(""); + println!(" borrows file_name line_number column_number"); + println!(" rustDocument/borrowInfo"); + println!(" used for 'borrow info'"); } diff --git a/src/custom_types.rs b/src/custom_types.rs new file mode 100644 index 00000000000..4d9890343e7 --- /dev/null +++ b/src/custom_types.rs @@ -0,0 +1,77 @@ +use lsp_data::Range; +use lsp_data::ls_util::rls_to_range; +use std::convert::From; +use analysis; + +#[derive(Debug, Serialize, Deserialize)] +pub struct BorrowData { + pub scopes: Vec, + pub loans: Vec, + pub moves: Vec, +} + +impl From for BorrowData { + fn from(borrows: analysis::BorrowData) -> BorrowData { + BorrowData { + scopes: borrows.scopes.into_iter().map(|a| a.into()).collect(), + moves: borrows.moves.into_iter().map(|m| m.into()).collect(), + loans: borrows.loans.into_iter().map(|l| l.into()).collect(), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum BorrowKind { + ImmBorrow, + MutBorrow, +} + +impl From for BorrowKind { + fn from(kind: analysis::BorrowKind) -> BorrowKind { + match kind { + analysis::BorrowKind::ImmBorrow => BorrowKind::ImmBorrow, + analysis::BorrowKind::MutBorrow => BorrowKind::MutBorrow, + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Loan { + pub kind: BorrowKind, + pub range: Range, +} + +impl From for Loan { + fn from(loan: analysis::Loan) -> Loan { + Loan { + kind: loan.kind.into(), + range: rls_to_range(loan.span.range), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Move { + pub range: Range, +} + +impl From for Move { + fn from(mov: analysis::Move) -> Move { + Move { + range: rls_to_range(mov.span.range), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Scope { + pub range: Range, +} + +impl From for Scope { + fn from(scope: analysis::Scope) -> Scope { + Scope { + range: rls_to_range(scope.span.range), + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 5c413c3ba47..60e4a5bfa39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,6 +48,7 @@ mod cmd; mod config; mod lsp_data; mod server; +mod custom_types; #[cfg(test)] mod test; diff --git a/src/server.rs b/src/server.rs index 6340f471954..792150344e8 100644 --- a/src/server.rs +++ b/src/server.rs @@ -15,6 +15,7 @@ use serde_json; use build::*; use lsp_data::*; use actions::ActionHandler; +use custom_types::BorrowData; use std::fmt; use std::io::{self, Read, Write, ErrorKind}; @@ -93,6 +94,7 @@ serializable_enum!(ResponseData, Locations(Vec), Highlights(Vec), HoverSuccess(Hover), + BorrowInfo(BorrowData), Commands(Vec), Ack(Ack) ); @@ -244,6 +246,7 @@ messages! { "textDocument/references" => References(ReferenceParams); "textDocument/completion" => Completion(TextDocumentPositionParams); "textDocument/documentHighlight" => DocumentHighlight(TextDocumentPositionParams); + "rustDocument/borrowInfo" => BorrowInfo(TextDocumentPositionParams); // currently, we safely ignore this as a pass-through since we fully handle // textDocument/completion. In the future, we may want to use this method as a // way to more lazily fill out completion information @@ -442,6 +445,7 @@ impl LsService { References(params) => { action: find_all_refs }; Completion(params) => { action: complete }; DocumentHighlight(params) => { action: highlight }; + BorrowInfo(params) => { action: borrow_info }; ResolveCompletionItem(params) => { this.output.success(id, ResponseData::CompletionItems(vec![params])) };