diff --git a/asm-lsp/handle.rs b/asm-lsp/handle.rs index 88fc70d0..8e759a9d 100644 --- a/asm-lsp/handle.rs +++ b/asm-lsp/handle.rs @@ -1,8 +1,6 @@ -use std::path::PathBuf; - use anyhow::{anyhow, Result}; use compile_commands::{CompilationDatabase, SourceFile}; -use log::{info, warn}; +use log::{error, info, warn}; use lsp_server::{Connection, Message, Notification, Request, RequestId, Response}; use lsp_types::{ notification::{ @@ -20,10 +18,7 @@ use lsp_types::{ use tree_sitter::Parser; use crate::{ - apply_compile_cmd, get_comp_resp, get_compile_cmd_for_req, get_default_compile_cmd, - get_document_symbols, get_goto_def_resp, get_hover_resp, get_ref_resp, get_sig_help_resp, - get_word_from_pos_params, send_empty_resp, text_doc_change_to_ts_edit, CompletionItems, Config, - ConfigOptions, DocumentStore, NameToInstructionMap, RootConfig, ServerStore, TreeEntry, + apply_compile_cmd, get_comp_resp, get_compile_cmd_for_req, get_default_compile_cmd, get_document_symbols, get_goto_def_resp, get_hover_resp, get_ref_resp, get_sig_help_resp, get_word_from_pos_params, process_uri, send_empty_resp, text_doc_change_to_ts_edit, CompletionItems, Config, ConfigOptions, DocumentStore, NameToInstructionMap, RootConfig, ServerStore, TreeEntry, UriConversion }; /// Handles `Request`s from the lsp client @@ -533,14 +528,33 @@ pub fn handle_diagnostics( cfg: &Config, compile_cmds: &CompilationDatabase, ) -> Result<()> { - let req_source_path = PathBuf::from(uri.path().as_str()); + let req_source_path = match process_uri(uri) { + UriConversion::Canonicalized(p) => p, + UriConversion::Unchecked(p) => { + error!( + "Failed to canonicalize request path {}, using {}", + uri.path().as_str(), + p.display() + ); + p + } + }; let source_entries = compile_cmds.iter().filter(|entry| match entry.file { SourceFile::File(ref file) => { - if file.is_absolute() { - file.eq(&req_source_path) - } else if let Ok(source_path) = file.canonicalize() { - source_path.eq(&req_source_path) + if let Ok(source_path) = file.canonicalize() { + // HACK: See comment inside `process_uri` + let cleaned_path = if cfg!(windows) { + if let Some(tmp) = source_path.to_str().unwrap().strip_prefix("\\\\?\\") { + warn!("Stripping Windows canonicalization prefix \"\\\\?\\\" from path"); + tmp.into() + } else { + source_path + } + } else { + source_path + }; + cleaned_path.eq(&req_source_path) } else { false } diff --git a/asm-lsp/lsp.rs b/asm-lsp/lsp.rs index 0992f017..5ded5cb0 100644 --- a/asm-lsp/lsp.rs +++ b/asm-lsp/lsp.rs @@ -176,7 +176,22 @@ pub fn process_uri(uri: &Uri) -> UriConversion { let Ok(path) = PathBuf::from_str(&clean_path); path.canonicalize() .map_or(UriConversion::Unchecked(path), |canonicalized| { - UriConversion::Canonicalized(canonicalized) + // HACK: On Windows, when a path is canonicalized, sometimes it gets prefixed + // with "\\?\" -- https://stackoverflow.com/questions/41233684/why-does-my-canonicalized-path-get-prefixed-with + // That's great and all, but it looks like common tools (like gcc) don't handle + // this correctly, and you get something like the following: + // Error: can't open //test.s for reading: No such file or directory + // The solution? Just cut out the prefix and hope that doesn't break anything else + if cfg!(windows) { + if let Some(tmp) = canonicalized.to_str().unwrap().strip_prefix("\\\\?\\") { + warn!("Stripping Windows canonicalization prefix \"\\\\?\\\" from path"); + UriConversion::Canonicalized(tmp.into()) + } else { + UriConversion::Canonicalized(canonicalized) + } + } else { + UriConversion::Canonicalized(canonicalized) + } }) }