aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-12-15 16:35:23 +0000
committerGitHub <[email protected]>2019-12-15 16:35:23 +0000
commit4e24b25c669965cf6a68c4b8e775cc83615d978a (patch)
tree7d44ca9749add5146d0672192d14df9de6c2e730 /crates/ra_lsp_server/src
parent4c1b2b921866279d014e377b958112b9e53edc52 (diff)
parent6fba427bf35bebdc7aa08a241ecbe83a2f725127 (diff)
Merge #2565
2565: Fixed syntax highlighting not refreshing on windows. r=matklad a=omerbenamram I was encoutering the same probelm described in #1690. It seems that events initiated by the frontend with `rust-analyzer/decorationsRequest` would go through. So whenever a user switches tabs, highlighting will update. However, when decorations are initiated by a notification with `rust-analyzer/publishDecorations`, it would fail on this check here https://github.com/rust-analyzer/rust-analyzer/blob/6cbd8a4a4bbca8a7656df9f3ef849acebbf9ef9b/editors/code/src/notifications/publish_decorations.ts#L15 (`targetEditor` will always be `undefined`). This is because it's trying to match the uri `rust-analyzer` sends (which uses an uppercase drive letter) to the uri provided at `editor.document.uri.toString()`, which is both escaped (uses `%3a` for `:`), and uses a lowercase letter drive. Aparrently this was an issue for some other extensions aswell - https://github.com/Microsoft/vscode/issues/68325. But this is the defined behavior - https://github.com/microsoft/vscode/blob/c110d84460b3e45842a8fe753562341003595e1d/src/vs/vscode.d.ts#L1304 This fix is only relevant for windows. I've opted for a server-side fix, since rust will always return uppercase letters for drives, there seems to be no other easy solution than manipulating the Url string before sending it to the frontend. Closes #1690. Co-authored-by: Omer Ben-Amram <[email protected]>
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r--crates/ra_lsp_server/src/world.rs68
1 files changed, 66 insertions, 2 deletions
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 927449b45..16cc11e8c 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};
17use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; 17use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
18use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; 18use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
19use relative_path::RelativePathBuf; 19use relative_path::RelativePathBuf;
20use std::path::{Component, Prefix};
20 21
21use crate::{ 22use crate::{
22 main_loop::pending_requests::{CompletedRequest, LatestRequests}, 23 main_loop::pending_requests::{CompletedRequest, LatestRequests},
23 LspError, Result, 24 LspError, Result,
24}; 25};
26use std::str::FromStr;
25 27
26#[derive(Debug, Clone)] 28#[derive(Debug, Clone)]
27pub struct Options { 29pub struct Options {
@@ -233,8 +235,8 @@ impl WorldSnapshot {
233 235
234 pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> { 236 pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> {
235 let path = self.vfs.read().file2path(VfsFile(id.0)); 237 let path = self.vfs.read().file2path(VfsFile(id.0));
236 let url = Url::from_file_path(&path) 238 let url = url_from_path_with_drive_lowercasing(path)?;
237 .map_err(|_| format!("can't convert path to url: {}", path.display()))?; 239
238 Ok(url) 240 Ok(url)
239 } 241 }
240 242
@@ -279,3 +281,65 @@ impl WorldSnapshot {
279 self.analysis.feature_flags() 281 self.analysis.feature_flags()
280 } 282 }
281} 283}
284
285/// Returns a `Url` object from a given path, will lowercase drive letters if present.
286/// This will only happen when processing windows paths.
287///
288/// When processing non-windows path, this is essentially the same as `Url::from_file_path`.
289fn url_from_path_with_drive_lowercasing(path: impl AsRef<Path>) -> Result<Url> {
290 let component_has_windows_drive = path
291 .as_ref()
292 .components()
293 .find(|comp| {
294 if let Component::Prefix(c) = comp {
295 match c.kind() {
296 Prefix::Disk(_) | Prefix::VerbatimDisk(_) => return true,
297 _ => return false,
298 }
299 }
300 false
301 })
302 .is_some();
303
304 // VSCode expects drive letters to be lowercased, where rust will uppercase the drive letters.
305 if component_has_windows_drive {
306 let url_original = Url::from_file_path(&path)
307 .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?;
308
309 let drive_partition: Vec<&str> = url_original.as_str().rsplitn(2, ':').collect();
310
311 // There is a drive partition, but we never found a colon.
312 // This should not happen, but in this case we just pass it through.
313 if drive_partition.len() == 1 {
314 return Ok(url_original);
315 }
316
317 let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0];
318 let url = Url::from_str(&joined).expect("This came from a valid `Url`");
319
320 Ok(url)
321 } else {
322 Ok(Url::from_file_path(&path)
323 .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?)
324 }
325}
326
327// `Url` is not able to parse windows paths on unix machines.
328#[cfg(target_os = "windows")]
329#[cfg(test)]
330mod path_conversion_windows_tests {
331 use super::url_from_path_with_drive_lowercasing;
332 #[test]
333 fn test_lowercase_drive_letter_with_drive() {
334 let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap();
335
336 assert_eq!(url.to_string(), "file:///c:/Test");
337 }
338
339 #[test]
340 fn test_drive_without_colon_passthrough() {
341 let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap();
342
343 assert_eq!(url.to_string(), "file://localhost/C$/my_dir");
344 }
345}