1- use lsp_types:: notification:: { Notification , PublishDiagnostics } ;
21use ropey:: Rope ;
32use ruff_python_ast:: { ModModule , PySourceType , Stmt } ;
43use ruff_python_parser:: { Parsed , Token , TokenKind } ;
54use lsp_types:: { Diagnostic , DiagnosticSeverity , MessageType , NumberOrString , Position , PublishDiagnosticsParams , Range , TextDocumentContentChangeEvent } ;
5+ use lsp_types:: notification:: { Notification , PublishDiagnostics } ;
66use tracing:: { error, warn} ;
77use std:: collections:: hash_map:: DefaultHasher ;
88use std:: collections:: HashSet ;
99use std:: hash:: { Hash , Hasher } ;
1010use std:: path:: PathBuf ;
1111use std:: str:: FromStr ;
12- use std:: sync:: Arc ;
12+ use std:: sync:: { atomic :: { AtomicBool , Ordering } , Arc , OnceLock } ;
1313use std:: { collections:: HashMap , fs} ;
1414use crate :: core:: config:: { DiagnosticFilter , DiagnosticFilterPathType } ;
1515use crate :: core:: diagnostics:: { create_diagnostic, DiagnosticCode , DiagnosticSetting } ;
@@ -24,6 +24,13 @@ use ruff_text_size::{Ranged, TextRange};
2424
2525use super :: odoo:: SyncOdoo ;
2626
27+ // Global static for legacy UNC path detection
28+ pub static LEGACY_UNC_PATHS : OnceLock < AtomicBool > = OnceLock :: new ( ) ;
29+
30+ pub fn legacy_unc_paths ( ) -> & ' static AtomicBool {
31+ LEGACY_UNC_PATHS . get_or_init ( || AtomicBool :: new ( false ) )
32+ }
33+
2734#[ derive( Debug , PartialEq , Clone ) ]
2835pub enum NoqaInfo {
2936 None ,
@@ -617,25 +624,34 @@ impl FileMgr {
617624 slash = "/" ;
618625 }
619626 // If the path starts with \\\\, we want to remove it and also set slash to empty string
620- // Such that we have file://wsl.localhost for example
627+ // Such that we have file://wsl.localhost/<path> for example
621628 // For normal paths we do want file:///C:/...
622- let replaced = if s. starts_with ( "\\ \\ " ) {
629+ // For some editors like PyCharm they use the legacy windows UNC urls so we have file:////wsl.localhost/<path>
630+ let ( replaced, unc) = if s. starts_with ( "\\ \\ " ) {
623631 slash = "" ;
624- s. replacen ( "\\ \\ " , "" , 1 )
632+ ( s. replacen ( "\\ \\ " , "" , 1 ) , true )
625633 } else {
626- s. clone ( )
634+ ( s. clone ( ) , false )
627635 } ;
628- let pre_uri = match url:: Url :: parse ( & format ! ( "file://{}{}" , slash, replaced) ) {
629- Ok ( pre_uri) => pre_uri,
636+ // Use legacy UNC flag to determine if we need four slashes
637+ let mut pre_uri = match url:: Url :: parse ( & format ! ( "file://{}{}" , slash, replaced) ) {
638+ Ok ( pre_uri) => pre_uri. to_string ( ) ,
630639 Err ( err) => panic ! ( "unable to transform pathname to uri: {s}, {}" , err)
631640 } ;
632- match lsp_types:: Uri :: from_str ( pre_uri. as_str ( ) ) {
641+ if unc && legacy_unc_paths ( ) . load ( Ordering :: Relaxed ) {
642+ pre_uri = pre_uri. replace ( "file://" , "file:////" ) ;
643+ }
644+ match lsp_types:: Uri :: from_str ( & pre_uri) {
633645 Ok ( url) => url,
634646 Err ( err) => panic ! ( "unable to transform pathname to uri: {s}, {}" , err)
635647 }
636648 }
637649
638650 pub fn uri2pathname ( s : & str ) -> String {
651+ // Detect legacy UNC path (file:////)
652+ if s. starts_with ( "file:////" ) {
653+ legacy_unc_paths ( ) . store ( true , Ordering :: Relaxed ) ;
654+ }
639655 let str_repr = s. replace ( "file:////" , "file://" ) ;
640656 if let Ok ( url) = url:: Url :: parse ( & str_repr) {
641657 if let Ok ( url) = url. to_file_path ( ) {
0 commit comments