@@ -8,6 +8,7 @@ use dashmap::{DashMap, DashSet};
88use globwalk:: FileType ;
99use log:: { debug, error, info} ;
1010use miette:: { diagnostic, IntoDiagnostic } ;
11+ use odoo_lsp:: utils:: isolate:: Isolate ;
1112use ropey:: Rope ;
1213use serde_json:: Value ;
1314use tower:: ServiceBuilder ;
@@ -37,6 +38,7 @@ pub struct Backend {
3738 capabilities : Capabilities ,
3839 root_setup : AtomicBool ,
3940 symbols_limit : AtomicUsize ,
41+ isolate : Isolate ,
4042}
4143
4244#[ derive( Debug , Default ) ]
@@ -135,6 +137,7 @@ impl LanguageServer for Backend {
135137 capabilities : _,
136138 root_setup : _,
137139 symbols_limit : _,
140+ isolate : _,
138141 } = self ;
139142 document_map. remove ( path) ;
140143 record_ranges. remove ( path) ;
@@ -408,7 +411,10 @@ impl LanguageServer for Backend {
408411 return Ok ( None ) ;
409412 } ;
410413 if ext == "xml" {
411- match self . xml_completions ( params, document. value ( ) . clone ( ) ) {
414+ let completions = self . isolate . send_task ( |send| {
415+ Box :: pin ( async { _ = send. send ( self . xml_completions ( params, document. value ( ) . clone ( ) ) . await ) } )
416+ } ) ;
417+ match completions. await . expect ( "isolate error" ) {
412418 Ok ( ret) => Ok ( ret) ,
413419 Err ( report) => {
414420 self . client
@@ -422,7 +428,15 @@ impl LanguageServer for Backend {
422428 debug ! ( "Bug: did not build AST for {}" , uri. path( ) ) ;
423429 return Ok ( None ) ;
424430 } ;
425- match self . python_completions ( params, ast. value ( ) . clone ( ) , document. value ( ) . clone ( ) ) {
431+ let completions = self . isolate . send_task ( |send| {
432+ Box :: pin ( async {
433+ _ = send. send (
434+ self . python_completions ( params, ast. value ( ) . clone ( ) , document. value ( ) . clone ( ) )
435+ . await ,
436+ ) ;
437+ } )
438+ } ) ;
439+ match completions. await . expect ( "isolate error" ) {
426440 Ok ( ret) => Ok ( ret) ,
427441 Err ( err) => {
428442 self . client
@@ -475,8 +489,9 @@ impl LanguageServer for Backend {
475489 #[ allow( deprecated) ]
476490 async fn symbol ( & self , params : WorkspaceSymbolParams ) -> Result < Option < Vec < SymbolInformation > > > {
477491 let query = & params. query ;
478- let records = self . module_index . records . iter ( ) . filter_map ( |entry| {
479- entry. id . contains ( query) . then ( || SymbolInformation {
492+ let records_by_prefix = self . module_index . records . by_prefix . read ( ) . await ;
493+ let records = records_by_prefix. iter_prefix ( query. as_bytes ( ) ) . flat_map ( |( _, key) | {
494+ self . module_index . records . get ( key) . map ( |entry| SymbolInformation {
480495 name : entry. id . to_string ( ) ,
481496 kind : SymbolKind :: VARIABLE ,
482497 tags : None ,
@@ -485,9 +500,10 @@ impl LanguageServer for Backend {
485500 container_name : None ,
486501 } )
487502 } ) ;
488- let models = self . module_index . models . iter ( ) . filter_map ( |entry| {
489- entry. 0 . as_ref ( ) . and_then ( |loc| {
490- entry. key ( ) . contains ( query) . then ( || SymbolInformation {
503+ let models_by_prefix = self . module_index . models . by_prefix . read ( ) . await ;
504+ let models = models_by_prefix. iter_prefix ( query. as_bytes ( ) ) . flat_map ( |( _, key) | {
505+ self . module_index . models . get ( key) . into_iter ( ) . flat_map ( |entry| {
506+ entry. 0 . as_ref ( ) . map ( |loc| SymbolInformation {
491507 name : entry. key ( ) . clone ( ) ,
492508 kind : SymbolKind :: CONSTANT ,
493509 tags : None ,
@@ -533,7 +549,8 @@ impl Backend {
533549 ( None , Text :: Delta ( _) ) => Err ( diagnostic ! ( "No rope and got delta" ) ) ?,
534550 } ;
535551 if matches ! ( split_uri, Some ( ( _, "xml" ) ) ) || matches ! ( params. language, Some ( Language :: Xml ) ) {
536- self . on_change_xml ( & params. text , & params. uri , rope, & mut diagnostics) ;
552+ self . on_change_xml ( & params. text , & params. uri , rope, & mut diagnostics)
553+ . await ;
537554 } else if matches ! ( split_uri, Some ( ( _, "py" ) ) ) || matches ! ( params. language, Some ( Language :: Python ) ) {
538555 self . on_change_python ( & params. text , & params. uri , rope, params. old_rope )
539556 . await ?;
@@ -652,20 +669,18 @@ impl Backend {
652669 items. extend ( matches) ;
653670 Ok ( ( ) )
654671 }
655- fn complete_model (
672+ async fn complete_model (
656673 & self ,
657674 needle : & str ,
658675 range : std:: ops:: Range < CharOffset > ,
659676 rope : Rope ,
660677 items : & mut Vec < CompletionItem > ,
661678 ) -> miette:: Result < ( ) > {
662679 let range = char_range_to_lsp_range ( range, rope) . ok_or_else ( || diagnostic ! ( "(complete_model) range" ) ) ?;
663- let matches = self
664- . module_index
665- . models
666- . iter ( )
667- . filter ( |entry| entry. key ( ) . contains ( needle) )
668- . take ( Self :: LIMIT )
680+ let by_prefix = self . module_index . models . by_prefix . read ( ) . await ;
681+ let matches = by_prefix
682+ . iter_prefix ( needle. as_bytes ( ) )
683+ . flat_map ( |( _, key) | self . module_index . models . get ( key) )
669684 . map ( |entry| {
670685 let label = entry. key ( ) . to_string ( ) ;
671686 CompletionItem {
@@ -711,37 +726,37 @@ impl Backend {
711726 None => Ok ( None ) ,
712727 }
713728 }
714- fn model_references ( & self , cursor_value : & str ) -> miette:: Result < Option < Vec < Location > > > {
715- let mut locations = match self . module_index . models . get ( cursor_value ) {
729+ fn model_references ( & self , model : & str ) -> miette:: Result < Option < Vec < Location > > > {
730+ let mut locations = match self . module_index . models . get ( model ) {
716731 Some ( entry) => entry. 1 . iter ( ) . map ( |loc| loc. 0 . clone ( ) ) . collect :: < Vec < _ > > ( ) ,
717732 None => vec ! [ ] ,
718733 } ;
719- let record_locations = self
720- . module_index
721- . records
722- . iter ( )
723- . filter_map ( |record| ( record. model . as_deref ( ) == Some ( cursor_value ) ) . then ( || record . location . clone ( ) ) ) ;
724- locations . extend ( record_locations ) ;
734+ locations . extend (
735+ self . module_index
736+ . records
737+ . by_model ( model )
738+ . map ( |record| record. location . clone ( ) ) ,
739+ ) ;
725740 Ok ( Some ( locations) )
726741 }
727742 fn record_references (
728743 & self ,
729- cursor_value : & str ,
744+ inherit_id : & str ,
730745 current_module : Option < & str > ,
731746 ) -> miette:: Result < Option < Vec < Location > > > {
732- let cursor_match = cursor_value . split_once ( '.' ) ;
733- let locations = self . module_index . records . iter ( ) . filter_map ( |entry| {
734- match ( & entry . module , & entry . inherit_id , cursor_match , current_module) {
735- ( _ , Some ( ( Some ( lhs_mod ) , lhs_id ) ) , Some ( ( rhs_mod , rhs_id ) ) , _ ) => {
736- lhs_mod == rhs_mod && lhs_id == rhs_id
737- }
738- ( lhs_mod , Some ( ( None , lhs_id ) ) , Some ( ( rhs_mod , rhs_id ) ) , _ ) => lhs_mod == rhs_mod && lhs_id == rhs_id ,
739- ( _ , Some ( ( Some ( lhs_mod ) , xml_id ) ) , None , Some ( rhs_mod ) ) => lhs_mod == rhs_mod && xml_id == cursor_value ,
740- ( lhs_mod , Some ( ( None , xml_id ) ) , None , Some ( rhs_mod ) ) => lhs_mod == rhs_mod && xml_id == cursor_value ,
741- _ => false ,
742- }
743- . then ( || entry . location . clone ( ) )
744- } ) ;
747+ let inherit_id = if inherit_id . contains ( '.' ) {
748+ Cow :: from ( inherit_id )
749+ } else if let Some ( current_module) = current_module {
750+ Cow :: from ( format ! ( "{}.{}" , current_module , inherit_id ) )
751+ } else {
752+ debug ! ( "No current module to resolve the XML ID {inherit_id}" ) ;
753+ return Ok ( None ) ;
754+ } ;
755+ let locations = self
756+ . module_index
757+ . records
758+ . by_inherit_id ( & inherit_id )
759+ . map ( |record| record . location . clone ( ) ) ;
745760 Ok ( Some ( locations. collect ( ) ) )
746761 }
747762 async fn on_change_config ( & self , config : Config ) {
@@ -791,7 +806,8 @@ async fn main() {
791806 capabilities : Default :: default ( ) ,
792807 root_setup : Default :: default ( ) ,
793808 ast_map : DashMap :: new ( ) ,
794- symbols_limit : AtomicUsize :: new ( 80 ) ,
809+ symbols_limit : AtomicUsize :: new ( 100 ) ,
810+ isolate : Isolate :: new ( ) ,
795811 } )
796812 . finish ( ) ;
797813
0 commit comments