@@ -10,7 +10,6 @@ use lsp_types::{
1010 DidOpenTextDocumentParams , DidSaveTextDocumentParams , WorkDoneProgressCancelParams ,
1111} ;
1212use paths:: Utf8PathBuf ;
13- use stdx:: TupleExt ;
1413use triomphe:: Arc ;
1514use vfs:: { AbsPathBuf , ChangeKind , VfsPath } ;
1615
@@ -75,7 +74,6 @@ pub(crate) fn handle_did_open_text_document(
7574 tracing:: error!( "duplicate DidOpenTextDocument: {}" , path) ;
7675 }
7776
78- tracing:: info!( "New file content set {:?}" , params. text_document. text) ;
7977 state. vfs . write ( ) . 0 . set_file_contents ( path, Some ( params. text_document . text . into_bytes ( ) ) ) ;
8078 if state. config . discover_workspace_config ( ) . is_some ( ) {
8179 tracing:: debug!( "queuing task" ) ;
@@ -296,41 +294,62 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
296294 let may_flycheck_workspace = state. config . flycheck_workspace ( None ) ;
297295 let mut updated = false ;
298296 let task = move || -> std:: result:: Result < ( ) , ide:: Cancelled > {
299- // Is the target binary? If so we let flycheck run only for the workspace that contains the crate.
300297 let target = TargetSpec :: for_file ( & world, file_id) ?. and_then ( |it| {
301298 let tgt_kind = it. target_kind ( ) ;
302- let ( tgt_name, crate_id ) = match it {
303- TargetSpec :: Cargo ( c) => ( c. target , c. crate_id ) ,
304- TargetSpec :: ProjectJson ( p ) => ( p . label , p . crate_id ) ,
299+ let ( tgt_name, root , package ) = match it {
300+ TargetSpec :: Cargo ( c) => ( c. target , c. workspace_root , c . package ) ,
301+ _ => return None ,
305302 } ;
306303
307304 let tgt = match tgt_kind {
308305 project_model:: TargetKind :: Bin => Target :: Bin ( tgt_name) ,
309306 project_model:: TargetKind :: Example => Target :: Example ( tgt_name) ,
310307 project_model:: TargetKind :: Test => Target :: Test ( tgt_name) ,
311308 project_model:: TargetKind :: Bench => Target :: Benchmark ( tgt_name) ,
312- _ => return None ,
309+ _ => return Some ( ( None , root , package ) ) ,
313310 } ;
314311
315- Some ( ( tgt, crate_id ) )
312+ Some ( ( Some ( tgt) , root , package ) )
316313 } ) ;
317-
318- let crate_ids = match target {
319- // Trigger flychecks for the only crate which the target belongs to
320- Some ( ( _, krate) ) => vec ! [ krate] ,
321- None => {
322- // Trigger flychecks for all workspaces that depend on the saved file
323- // Crates containing or depending on the saved file
324- world
325- . analysis
326- . crates_for ( file_id) ?
327- . into_iter ( )
328- . flat_map ( |id| world. analysis . transitive_rev_deps ( id) )
329- . flatten ( )
330- . unique ( )
331- . collect :: < Vec < _ > > ( )
314+ tracing:: debug!( ?target, "flycheck target" ) ;
315+ // we have a specific non-library target, attempt to only check that target, nothing
316+ // else will be affected
317+ if let Some ( ( target, root, package) ) = target {
318+ // trigger a package check if we have a non-library target as that can't affect
319+ // anything else in the workspace OR if we're not allowed to check the workspace as
320+ // the user opted into package checks then
321+ let package_check_allowed = target. is_some ( ) || !may_flycheck_workspace;
322+ if package_check_allowed {
323+ let workspace =
324+ world. workspaces . iter ( ) . enumerate ( ) . find ( |( _, ws) | match & ws. kind {
325+ project_model:: ProjectWorkspaceKind :: Cargo { cargo, .. }
326+ | project_model:: ProjectWorkspaceKind :: DetachedFile {
327+ cargo : Some ( ( cargo, _, _) ) ,
328+ ..
329+ } => * cargo. workspace_root ( ) == root,
330+ _ => false ,
331+ } ) ;
332+ if let Some ( ( idx, _) ) = workspace {
333+ world. flycheck [ idx] . restart_for_package ( package, target) ;
334+ }
332335 }
333- } ;
336+ }
337+
338+ if !may_flycheck_workspace {
339+ return Ok ( ( ) ) ;
340+ }
341+
342+ // Trigger flychecks for all workspaces that depend on the saved file
343+ // Crates containing or depending on the saved file
344+ let crate_ids = world
345+ . analysis
346+ . crates_for ( file_id) ?
347+ . into_iter ( )
348+ . flat_map ( |id| world. analysis . transitive_rev_deps ( id) )
349+ . flatten ( )
350+ . unique ( )
351+ . collect :: < Vec < _ > > ( ) ;
352+ tracing:: debug!( ?crate_ids, "flycheck crate ids" ) ;
334353 let crate_root_paths: Vec < _ > = crate_ids
335354 . iter ( )
336355 . filter_map ( |& crate_id| {
@@ -344,53 +363,41 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
344363 } )
345364 . collect :: < ide:: Cancellable < _ > > ( ) ?;
346365 let crate_root_paths: Vec < _ > = crate_root_paths. iter ( ) . map ( Deref :: deref) . collect ( ) ;
366+ tracing:: debug!( ?crate_root_paths, "flycheck crate roots" ) ;
347367
348368 // Find all workspaces that have at least one target containing the saved file
349- let workspace_ids = world . workspaces . iter ( ) . enumerate ( ) . filter_map ( | ( idx , ws ) | {
350- let package = match & ws. kind {
369+ let workspace_ids =
370+ world . workspaces . iter ( ) . enumerate ( ) . filter ( | ( _ , ws ) | match & ws. kind {
351371 project_model:: ProjectWorkspaceKind :: Cargo { cargo, .. }
352372 | project_model:: ProjectWorkspaceKind :: DetachedFile {
353373 cargo : Some ( ( cargo, _, _) ) ,
354374 ..
355- } => cargo. packages ( ) . find_map ( |pkg| {
356- let has_target_with_root = cargo[ pkg]
375+ } => cargo. packages ( ) . any ( |pkg| {
376+ cargo[ pkg]
357377 . targets
358378 . iter ( )
359- . any ( |& it| crate_root_paths. contains ( & cargo[ it] . root . as_path ( ) ) ) ;
360- has_target_with_root. then ( || cargo. package_flag ( & cargo[ pkg] ) )
379+ . any ( |& it| crate_root_paths. contains ( & cargo[ it] . root . as_path ( ) ) )
361380 } ) ,
362- project_model:: ProjectWorkspaceKind :: Json ( project) => {
363- if !project. crates ( ) . any ( |( _, krate) | {
364- crate_root_paths. contains ( & krate. root_module . as_path ( ) )
365- } ) {
366- return None ;
367- }
368- None
369- }
370- project_model:: ProjectWorkspaceKind :: DetachedFile { .. } => return None ,
371- } ;
372- Some ( ( idx, package) )
373- } ) ;
381+ project_model:: ProjectWorkspaceKind :: Json ( project) => project
382+ . crates ( )
383+ . any ( |( _, krate) | crate_root_paths. contains ( & krate. root_module . as_path ( ) ) ) ,
384+ project_model:: ProjectWorkspaceKind :: DetachedFile { .. } => false ,
385+ } ) ;
374386
375387 let saved_file = vfs_path. as_path ( ) . map ( |p| p. to_owned ( ) ) ;
376388
377389 // Find and trigger corresponding flychecks
378390 ' flychecks: for flycheck in world. flycheck . iter ( ) {
379- for ( id, package ) in workspace_ids. clone ( ) {
391+ for ( id, _ ) in workspace_ids. clone ( ) {
380392 if id == flycheck. id ( ) {
381393 updated = true ;
382- if may_flycheck_workspace {
383- flycheck. restart_workspace ( saved_file. clone ( ) )
384- } else if let Some ( package) = package {
385- flycheck
386- . restart_for_package ( package, target. clone ( ) . map ( TupleExt :: head) )
387- }
394+ flycheck. restart_workspace ( saved_file. clone ( ) ) ;
388395 continue ' flychecks;
389396 }
390397 }
391398 }
392399 // No specific flycheck was triggered, so let's trigger all of them.
393- if !updated && may_flycheck_workspace {
400+ if !updated {
394401 for flycheck in world. flycheck . iter ( ) {
395402 flycheck. restart_workspace ( saved_file. clone ( ) ) ;
396403 }
0 commit comments