@@ -531,10 +531,25 @@ impl Translator {
531531 /// Get a cloned LSP client for a file path based on language detection.
532532 fn get_client_for_file ( & self , path : & Path ) -> Result < LspClient > {
533533 let language_id = detect_language ( path, & self . extension_map ) ;
534- self . lsp_clients
535- . get ( & language_id)
536- . cloned ( )
537- . ok_or ( Error :: NoServerForLanguage ( language_id) )
534+ if let Some ( client) = self . lsp_clients . get ( & language_id) {
535+ return Ok ( client. clone ( ) ) ;
536+ }
537+
538+ if let Some ( server_language_id) = Self :: server_language_id_for_document ( & language_id)
539+ && let Some ( client) = self . lsp_clients . get ( server_language_id)
540+ {
541+ return Ok ( client. clone ( ) ) ;
542+ }
543+
544+ Err ( Error :: NoServerForLanguage ( language_id) )
545+ }
546+
547+ fn server_language_id_for_document ( language_id : & str ) -> Option < & ' static str > {
548+ match language_id {
549+ "javascriptreact" => Some ( "javascript" ) ,
550+ "typescriptreact" => Some ( "typescript" ) ,
551+ _ => None ,
552+ }
538553 }
539554
540555 /// Parse and validate a file URI, returning the validated path.
@@ -3209,6 +3224,51 @@ mod tests {
32093224 }
32103225 }
32113226
3227+ #[ test]
3228+ fn test_get_client_for_file_routes_tsx_to_typescript_server ( ) {
3229+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
3230+ let test_file = temp_dir. path ( ) . join ( "component.tsx" ) ;
3231+ fs:: write ( & test_file, "export const Component = () => <div />" ) . unwrap ( ) ;
3232+
3233+ let mut extension_map = HashMap :: new ( ) ;
3234+ extension_map. insert ( "tsx" . to_string ( ) , "typescriptreact" . to_string ( ) ) ;
3235+
3236+ let mut translator = Translator :: new ( ) . with_extensions ( extension_map) ;
3237+ translator. register_client (
3238+ "typescript" . to_string ( ) ,
3239+ LspClient :: new ( crate :: config:: LspServerConfig :: typescript ( ) ) ,
3240+ ) ;
3241+
3242+ let client = translator. get_client_for_file ( & test_file) . unwrap ( ) ;
3243+ assert_eq ! ( client. language_id( ) , "typescript" ) ;
3244+ }
3245+
3246+ #[ test]
3247+ fn test_get_client_for_file_routes_jsx_to_javascript_server ( ) {
3248+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
3249+ let test_file = temp_dir. path ( ) . join ( "component.jsx" ) ;
3250+ fs:: write ( & test_file, "export const Component = () => <div />" ) . unwrap ( ) ;
3251+
3252+ let mut extension_map = HashMap :: new ( ) ;
3253+ extension_map. insert ( "jsx" . to_string ( ) , "javascriptreact" . to_string ( ) ) ;
3254+
3255+ let javascript_config = crate :: config:: LspServerConfig {
3256+ language_id : "javascript" . to_string ( ) ,
3257+ command : "typescript-language-server" . to_string ( ) ,
3258+ args : vec ! [ "--stdio" . to_string( ) ] ,
3259+ env : HashMap :: new ( ) ,
3260+ file_patterns : vec ! [ "**/*.js" . to_string( ) , "**/*.jsx" . to_string( ) ] ,
3261+ initialization_options : None ,
3262+ timeout_seconds : 30 ,
3263+ heuristics : None ,
3264+ } ;
3265+ let mut translator = Translator :: new ( ) . with_extensions ( extension_map) ;
3266+ translator. register_client ( "javascript" . to_string ( ) , LspClient :: new ( javascript_config) ) ;
3267+
3268+ let client = translator. get_client_for_file ( & test_file) . unwrap ( ) ;
3269+ assert_eq ! ( client. language_id( ) , "javascript" ) ;
3270+ }
3271+
32123272 #[ tokio:: test]
32133273 async fn test_serve_initializes_translator_with_extensions ( ) {
32143274 use crate :: config:: { LanguageExtensionMapping , WorkspaceConfig } ;
0 commit comments