@@ -21,7 +21,7 @@ use pet_core::{
2121 Configuration , Locator , RefreshStatePersistence , RefreshStateSyncScope ,
2222} ;
2323use pet_env_var_path:: get_search_paths_from_env_variables;
24- use pet_fs:: glob:: expand_glob_patterns;
24+ use pet_fs:: glob:: { expand_glob_pattern , expand_glob_patterns, is_recursive_glob_pattern } ;
2525use pet_fs:: path:: norm_case;
2626use pet_jsonrpc:: {
2727 send_error, send_reply,
@@ -566,6 +566,43 @@ pub struct ConfigureOptions {
566566/// The client has a 30-second timeout for configure requests.
567567const GLOB_EXPANSION_WARN_THRESHOLD : Duration = Duration :: from_secs ( 5 ) ;
568568
569+ fn expand_configure_directory_patterns ( kind : & str , patterns : Vec < PathBuf > ) -> Vec < PathBuf > {
570+ patterns
571+ . into_iter ( )
572+ . flat_map ( |pattern| {
573+ let start = Instant :: now ( ) ;
574+ let expanded = expand_glob_pattern ( & pattern. to_string_lossy ( ) ) ;
575+ let elapsed = start. elapsed ( ) ;
576+ trace ! (
577+ "Expanded {} pattern '{}' in {:?}" ,
578+ kind,
579+ pattern. display( ) ,
580+ elapsed
581+ ) ;
582+ if elapsed >= GLOB_EXPANSION_WARN_THRESHOLD {
583+ warn ! (
584+ "Expanding {} pattern '{}' took {:?}, this may cause client timeouts" ,
585+ kind,
586+ pattern. display( ) ,
587+ elapsed
588+ ) ;
589+ }
590+ expanded
591+ } )
592+ . filter ( |path| path. is_dir ( ) )
593+ . collect ( )
594+ }
595+
596+ fn warn_for_recursive_environment_patterns ( patterns : & [ PathBuf ] ) {
597+ for pattern in patterns {
598+ if is_recursive_glob_pattern ( & pattern. to_string_lossy ( ) ) {
599+ warn ! (
600+ "Recursive environmentDirectories pattern '{}' can make configure slow; prefer bounded patterns such as '.venv' or '*/.venv'" ,
601+ pattern. display( )
602+ ) ;
603+ }
604+ }
605+ }
569606pub fn handle_configure ( context : Arc < Context > , id : u32 , params : Value ) {
570607 match serde_json:: from_value :: < ConfigureOptions > ( params. clone ( ) ) {
571608 Ok ( mut configure_options) => {
@@ -574,38 +611,28 @@ pub fn handle_configure(context: Arc<Context>, id: u32, params: Value) {
574611 thread:: spawn ( move || {
575612 let now = Instant :: now ( ) ;
576613
614+ // Warn before any expansion so a slow workspace pattern cannot delay
615+ // the actionable environmentDirectories diagnostic.
616+ if let Some ( patterns) = configure_options. environment_directories . as_deref ( ) {
617+ warn_for_recursive_environment_patterns ( patterns) ;
618+ }
619+
577620 // Expand glob patterns before acquiring the write lock so we
578621 // don't block readers/writers while traversing the filesystem.
579622 let workspace_directories =
580- configure_options. workspace_directories . take ( ) . map ( |dirs| {
581- let start = Instant :: now ( ) ;
582- let result: Vec < PathBuf > = expand_glob_patterns ( & dirs)
583- . into_iter ( )
584- . filter ( |p| p. is_dir ( ) )
585- . collect ( ) ;
586- trace ! (
587- "Expanded workspace directory patterns ({:?}) in {:?}" ,
588- dirs,
589- start. elapsed( )
590- ) ;
591- result
592- } ) ;
623+ configure_options
624+ . workspace_directories
625+ . take ( )
626+ . map ( |patterns| {
627+ expand_configure_directory_patterns ( "workspaceDirectories" , patterns)
628+ } ) ;
593629 let environment_directories =
594630 configure_options
595631 . environment_directories
596632 . take ( )
597- . map ( |dirs| {
598- let start = Instant :: now ( ) ;
599- let result: Vec < PathBuf > = expand_glob_patterns ( & dirs)
600- . into_iter ( )
601- . filter ( |p| p. is_dir ( ) )
602- . collect ( ) ;
603- trace ! (
604- "Expanded environment directory patterns ({:?}) in {:?}" ,
605- dirs,
606- start. elapsed( )
607- ) ;
608- result
633+ . map ( |patterns| {
634+ warn_for_recursive_environment_patterns ( & patterns) ;
635+ expand_configure_directory_patterns ( "environmentDirectories" , patterns)
609636 } ) ;
610637 let glob_elapsed = now. elapsed ( ) ;
611638 trace ! ( "Glob expansion completed in {:?}" , glob_elapsed) ;
0 commit comments