From 1d9b585c62dc92889380c9ae130d15ce7f9b08d4 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 15:07:33 +0200 Subject: make drive comparison case-insensitive. --- editors/code/src/notifications/publish_decorations.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 00ffb7776..120eabbc6 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -10,10 +10,19 @@ export interface PublishDecorationsParams { export function handle(params: PublishDecorationsParams) { const targetEditor = vscode.window.visibleTextEditors.find( - editor => editor.document.uri.toString() === params.uri, + editor => { + const unescapedUri = unescape(editor.document.uri.toString()); + // Unescaped URI should be something like: + // file:///c:/Workspace/ra-test/src/main.rs + // RA server might send it with the drive letter uppercased, so we force only the drive letter to lowercase. + const uriWithLowercasedDrive = params.uri.substr(0, 8) + params.uri[8].toLowerCase() + params.uri.substr(9); + return unescapedUri === uriWithLowercasedDrive + } ); + if (!Server.config.highlightingOn || !targetEditor) { return; } + Server.highlighter.setHighlights(targetEditor, params.decorations); } -- cgit v1.2.3 From 324cbe839f3110bd4d51726d5a7afe29808ade02 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 16:51:57 +0200 Subject: Lowercase drive letters on windows before sending to extension. --- crates/ra_lsp_server/src/world.rs | 34 ++++++++++++++++++++++ .../code/src/notifications/publish_decorations.ts | 3 +- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 927449b45..be3a5bfb8 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -22,6 +22,7 @@ use crate::{ main_loop::pending_requests::{CompletedRequest, LatestRequests}, LspError, Result, }; +use std::str::FromStr; #[derive(Debug, Clone)] pub struct Options { @@ -235,6 +236,9 @@ impl WorldSnapshot { let path = self.vfs.read().file2path(VfsFile(id.0)); let url = Url::from_file_path(&path) .map_err(|_| format!("can't convert path to url: {}", path.display()))?; + + #[cfg(target_os = "windows")] + let url = lowercase_drive_letter(&url); Ok(url) } @@ -279,3 +283,33 @@ impl WorldSnapshot { self.analysis.feature_flags() } } + +#[cfg(target_os = "windows")] +fn lowercase_drive_letter(url: &Url) -> Url { + let s = url.to_string(); + let drive_partition: Vec<&str> = s.rsplitn(2, ':').collect::>(); + + if drive_partition.len() == 1 { + return url.clone(); + } + + let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0]; + let url = Url::from_str(&joined).expect("This came from a valid `Url`"); + url +} + +#[test] +fn test_lowercase_drive_letter_with_drive() { + let url = Url::from_file_path("C:\\Test").unwrap(); + let url = lowercase_drive_letter(&url); + + assert_eq!(url.to_string(), "file:///c:/Test"); +} + +#[test] +fn test_drive_without_colon_passthrough() { + let url = Url::from_file_path(r#"\\localhost\C$\my_dir"#).expect("Should work"); + let url = lowercase_drive_letter(&url); + + assert_eq!(url.to_string(), "file:///C$/my_dir"); +} diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 120eabbc6..4441e2b28 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -15,8 +15,7 @@ export function handle(params: PublishDecorationsParams) { // Unescaped URI should be something like: // file:///c:/Workspace/ra-test/src/main.rs // RA server might send it with the drive letter uppercased, so we force only the drive letter to lowercase. - const uriWithLowercasedDrive = params.uri.substr(0, 8) + params.uri[8].toLowerCase() + params.uri.substr(9); - return unescapedUri === uriWithLowercasedDrive + return unescapedUri === params.uri } ); -- cgit v1.2.3 From 498a7912e923ad8ce349f6874568373f430e9602 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 16:55:39 +0200 Subject: fixed comment --- editors/code/src/notifications/publish_decorations.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 4441e2b28..2ccd2d585 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -12,9 +12,8 @@ export function handle(params: PublishDecorationsParams) { const targetEditor = vscode.window.visibleTextEditors.find( editor => { const unescapedUri = unescape(editor.document.uri.toString()); - // Unescaped URI should be something like: + // Unescaped URI looks like: // file:///c:/Workspace/ra-test/src/main.rs - // RA server might send it with the drive letter uppercased, so we force only the drive letter to lowercase. return unescapedUri === params.uri } ); -- cgit v1.2.3 From ebf302d2610527c35b8fb794a03cc1c280c8a9d3 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 17:03:39 +0200 Subject: move import inside cfg block --- crates/ra_lsp_server/src/world.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index be3a5bfb8..f139a5728 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -22,7 +22,6 @@ use crate::{ main_loop::pending_requests::{CompletedRequest, LatestRequests}, LspError, Result, }; -use std::str::FromStr; #[derive(Debug, Clone)] pub struct Options { @@ -286,6 +285,8 @@ impl WorldSnapshot { #[cfg(target_os = "windows")] fn lowercase_drive_letter(url: &Url) -> Url { + use std::str::FromStr; + let s = url.to_string(); let drive_partition: Vec<&str> = s.rsplitn(2, ':').collect::>(); -- cgit v1.2.3 From 75353753cdcb993c277ce1d8bb366c708eabe2c6 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 17:10:39 +0200 Subject: `npm run fix` --- editors/code/src/notifications/publish_decorations.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 2ccd2d585..f23e286ad 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -9,14 +9,12 @@ export interface PublishDecorationsParams { } export function handle(params: PublishDecorationsParams) { - const targetEditor = vscode.window.visibleTextEditors.find( - editor => { - const unescapedUri = unescape(editor.document.uri.toString()); - // Unescaped URI looks like: - // file:///c:/Workspace/ra-test/src/main.rs - return unescapedUri === params.uri - } - ); + const targetEditor = vscode.window.visibleTextEditors.find(editor => { + const unescapedUri = unescape(editor.document.uri.toString()); + // Unescaped URI looks like: + // file:///c:/Workspace/ra-test/src/main.rs + return unescapedUri === params.uri; + }); if (!Server.config.highlightingOn || !targetEditor) { return; -- cgit v1.2.3 From 2e2fae32dff6cab508768953bbd34b88b5bea166 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 17:46:00 +0200 Subject: improved path checking to consider only paths that may contain a windows drive. --- crates/ra_lsp_server/src/world.rs | 64 +++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index f139a5728..63a820012 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -17,11 +17,13 @@ use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; use relative_path::RelativePathBuf; +use std::path::{Component, Prefix}; use crate::{ main_loop::pending_requests::{CompletedRequest, LatestRequests}, LspError, Result, }; +use std::str::FromStr; #[derive(Debug, Clone)] pub struct Options { @@ -233,11 +235,8 @@ impl WorldSnapshot { pub fn file_id_to_uri(&self, id: FileId) -> Result { let path = self.vfs.read().file2path(VfsFile(id.0)); - let url = Url::from_file_path(&path) - .map_err(|_| format!("can't convert path to url: {}", path.display()))?; + let url = url_from_path_with_drive_lowercasing(path)?; - #[cfg(target_os = "windows")] - let url = lowercase_drive_letter(&url); Ok(url) } @@ -283,34 +282,59 @@ impl WorldSnapshot { } } -#[cfg(target_os = "windows")] -fn lowercase_drive_letter(url: &Url) -> Url { - use std::str::FromStr; +/// Returns a `Url` object from a given path, will lowercase drive letters if present. +/// This will only happen when processing windows paths. +/// +/// When processing non-windows path, this is essentially the same as `Url::from_file_path`. +fn url_from_path_with_drive_lowercasing(path: impl AsRef) -> Result { + let component_has_windows_drive = path + .as_ref() + .components() + .find(|comp| { + if let Component::Prefix(c) = comp { + match c.kind() { + Prefix::Disk(_) | Prefix::VerbatimDisk(_) => return true, + _ => return false, + } + } + false + }) + .is_some(); + + // VSCode expects drive letters to be lowercased, where rust will uppercase the drive letters. + if component_has_windows_drive { + let url_original = Url::from_file_path(&path) + .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?; + + let drive_partition: Vec<&str> = + url_original.as_str().rsplitn(2, ':').collect::>(); + + // There is a drive partition, but we never found a colon. + // This should not happen, but in this case we just pass it through. + if drive_partition.len() == 1 { + return Ok(url_original); + } - let s = url.to_string(); - let drive_partition: Vec<&str> = s.rsplitn(2, ':').collect::>(); + let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0]; + let url = Url::from_str(&joined).expect("This came from a valid `Url`"); - if drive_partition.len() == 1 { - return url.clone(); + Ok(url) + } else { + Ok(Url::from_file_path(&path) + .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?) } - - let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0]; - let url = Url::from_str(&joined).expect("This came from a valid `Url`"); - url } #[test] fn test_lowercase_drive_letter_with_drive() { - let url = Url::from_file_path("C:\\Test").unwrap(); - let url = lowercase_drive_letter(&url); + let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap(); assert_eq!(url.to_string(), "file:///c:/Test"); } #[test] fn test_drive_without_colon_passthrough() { - let url = Url::from_file_path(r#"\\localhost\C$\my_dir"#).expect("Should work"); - let url = lowercase_drive_letter(&url); + let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap(); - assert_eq!(url.to_string(), "file:///C$/my_dir"); + assert_eq!(url.to_string(), "file://localhost/C$/my_dir"); } -- cgit v1.2.3 From 40116af598ef51cab8a1059dceda7508f994387c Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 17:54:24 +0200 Subject: cfg gated tests that only work on windows. --- crates/ra_lsp_server/src/world.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 63a820012..8b48726ee 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -325,16 +325,22 @@ fn url_from_path_with_drive_lowercasing(path: impl AsRef) -> Result { } } -#[test] -fn test_lowercase_drive_letter_with_drive() { - let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap(); - - assert_eq!(url.to_string(), "file:///c:/Test"); -} +// `Url` is not able to parse windows paths on unix machines. +#[cfg(target_os = "windows")] +#[cfg(test)] +mod path_conversion_windows_tests { + use super::url_from_path_with_drive_lowercasing; + #[test] + fn test_lowercase_drive_letter_with_drive() { + let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap(); + + assert_eq!(url.to_string(), "file:///c:/Test"); + } -#[test] -fn test_drive_without_colon_passthrough() { - let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap(); + #[test] + fn test_drive_without_colon_passthrough() { + let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap(); - assert_eq!(url.to_string(), "file://localhost/C$/my_dir"); + assert_eq!(url.to_string(), "file://localhost/C$/my_dir"); + } } -- cgit v1.2.3 From 6fba427bf35bebdc7aa08a241ecbe83a2f725127 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 18:15:24 +0200 Subject: remove unnecessary turbofish. --- crates/ra_lsp_server/src/world.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 8b48726ee..16cc11e8c 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -306,8 +306,7 @@ fn url_from_path_with_drive_lowercasing(path: impl AsRef) -> Result { let url_original = Url::from_file_path(&path) .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?; - let drive_partition: Vec<&str> = - url_original.as_str().rsplitn(2, ':').collect::>(); + let drive_partition: Vec<&str> = url_original.as_str().rsplitn(2, ':').collect(); // There is a drive partition, but we never found a colon. // This should not happen, but in this case we just pass it through. -- cgit v1.2.3