@@ -14,7 +14,7 @@ use pg_workspace::workspace::IsPathIgnoredParams;
1414use pg_workspace:: { Workspace , WorkspaceError } ;
1515use rustc_hash:: FxHashSet ;
1616use std:: collections:: BTreeSet ;
17- use std:: sync:: atomic:: AtomicU32 ;
17+ use std:: sync:: atomic:: { AtomicBool , AtomicU32 } ;
1818use std:: sync:: RwLock ;
1919use std:: {
2020 env:: current_dir,
@@ -33,6 +33,7 @@ pub(crate) struct TraverseResult {
3333 pub ( crate ) summary : TraversalSummary ,
3434 pub ( crate ) evaluated_paths : BTreeSet < PgLspPath > ,
3535 pub ( crate ) diagnostics : Vec < Error > ,
36+ pub ( crate ) user_hints : Vec < String > ,
3637}
3738
3839pub ( crate ) fn traverse (
@@ -72,6 +73,7 @@ pub(crate) fn traverse(
7273 let unchanged = AtomicUsize :: new ( 0 ) ;
7374 let matches = AtomicUsize :: new ( 0 ) ;
7475 let skipped = AtomicUsize :: new ( 0 ) ;
76+ let skipped_db_conn = AtomicBool :: new ( false ) ;
7577
7678 let fs = & * session. app . fs ;
7779 let workspace = & * session. app . workspace ;
@@ -84,7 +86,7 @@ pub(crate) fn traverse(
8486 . with_diagnostic_level ( cli_options. diagnostic_level )
8587 . with_max_diagnostics ( max_diagnostics) ;
8688
87- let ( duration, evaluated_paths, diagnostics) = thread:: scope ( |s| {
89+ let ( duration, evaluated_paths, diagnostics, mut user_hints ) = thread:: scope ( |s| {
8890 let handler = thread:: Builder :: new ( )
8991 . name ( String :: from ( "pglsp::console" ) )
9092 . spawn_scoped ( s, || printer. run ( receiver, recv_files) )
@@ -104,15 +106,16 @@ pub(crate) fn traverse(
104106 changed : & changed,
105107 unchanged : & unchanged,
106108 skipped : & skipped,
109+ skipped_db_conn : & skipped_db_conn,
107110 messages : sender,
108111 remaining_diagnostics : & remaining_diagnostics,
109112 evaluated_paths : RwLock :: default ( ) ,
110113 } ,
111114 ) ;
112115 // wait for the main thread to finish
113- let diagnostics = handler. join ( ) . unwrap ( ) ;
116+ let ( diagnostics, user_hints ) = handler. join ( ) . unwrap ( ) ;
114117
115- ( elapsed, evaluated_paths, diagnostics)
118+ ( elapsed, evaluated_paths, diagnostics, user_hints )
116119 } ) ;
117120
118121 let errors = printer. errors ( ) ;
@@ -123,6 +126,20 @@ pub(crate) fn traverse(
123126 let skipped = skipped. load ( Ordering :: Relaxed ) ;
124127 let suggested_fixes_skipped = printer. skipped_fixes ( ) ;
125128 let diagnostics_not_printed = printer. not_printed_diagnostics ( ) ;
129+
130+ if duration. as_secs ( ) >= 2 {
131+ user_hints. push ( format ! (
132+ "The traversal took longer than expected ({}s). Consider using the `--skip-db` option if your Postgres connection is slow." ,
133+ duration. as_secs( )
134+ ) ) ;
135+ }
136+
137+ if skipped_db_conn. load ( Ordering :: Relaxed ) {
138+ user_hints. push ( format ! (
139+ "Skipped all checks requiring database connections." ,
140+ ) ) ;
141+ }
142+
126143 Ok ( TraverseResult {
127144 summary : TraversalSummary {
128145 changed,
@@ -137,6 +154,7 @@ pub(crate) fn traverse(
137154 } ,
138155 evaluated_paths,
139156 diagnostics,
157+ user_hints,
140158 } )
141159}
142160
@@ -288,10 +306,15 @@ impl<'ctx> DiagnosticsPrinter<'ctx> {
288306 should_print
289307 }
290308
291- fn run ( & self , receiver : Receiver < Message > , interner : Receiver < PathBuf > ) -> Vec < Error > {
309+ fn run (
310+ & self ,
311+ receiver : Receiver < Message > ,
312+ interner : Receiver < PathBuf > ,
313+ ) -> ( Vec < Error > , Vec < String > ) {
292314 let mut paths: FxHashSet < String > = FxHashSet :: default ( ) ;
293315
294316 let mut diagnostics_to_print = vec ! [ ] ;
317+ let mut hints_to_print = vec ! [ ] ;
295318
296319 while let Ok ( msg) = receiver. recv ( ) {
297320 match msg {
@@ -306,6 +329,10 @@ impl<'ctx> DiagnosticsPrinter<'ctx> {
306329 self . errors . fetch_add ( 1 , Ordering :: Relaxed ) ;
307330 }
308331
332+ Message :: Hint ( hint) => {
333+ hints_to_print. push ( hint) ;
334+ }
335+
309336 Message :: Error ( mut err) => {
310337 let location = err. location ( ) ;
311338 if self . should_skip_diagnostic ( err. severity ( ) , err. tags ( ) ) {
@@ -381,7 +408,8 @@ impl<'ctx> DiagnosticsPrinter<'ctx> {
381408 }
382409 }
383410 }
384- diagnostics_to_print
411+
412+ ( diagnostics_to_print, hints_to_print)
385413 }
386414}
387415
@@ -403,6 +431,8 @@ pub(crate) struct TraversalOptions<'ctx, 'app> {
403431 matches : & ' ctx AtomicUsize ,
404432 /// Shared atomic counter storing the number of skipped files
405433 skipped : & ' ctx AtomicUsize ,
434+ /// Shared atomic bool tracking whether we used a DB connection
435+ skipped_db_conn : & ' ctx AtomicBool ,
406436 /// Channel sending messages to the display thread
407437 pub ( crate ) messages : Sender < Message > ,
408438 /// The approximate number of diagnostics the console will print before
@@ -434,6 +464,10 @@ impl TraversalOptions<'_, '_> {
434464 self . messages . send ( msg. into ( ) ) . ok ( ) ;
435465 }
436466
467+ pub ( crate ) fn set_skipped_db_conn ( & self , has_skipped : bool ) {
468+ self . skipped_db_conn . store ( has_skipped, Ordering :: Relaxed ) ;
469+ }
470+
437471 pub ( crate ) fn protected_file ( & self , pglsp_path : & PgLspPath ) {
438472 self . push_diagnostic (
439473 WorkspaceError :: protected_file ( pglsp_path. display ( ) . to_string ( ) ) . into ( ) ,
0 commit comments