@@ -54,14 +54,21 @@ package struct SourceFileInfo: Sendable {
5454  /// from non-test targets or files that don't actually contain any tests.
5555  package var  mayContainTests :  Bool 
5656
57+   /// Source files returned here fall into two categories:
58+   ///  - Buildable source files are files that can be built by the build system and that make sense to background index
59+   ///  - Non-buildable source files include eg. the SwiftPM package manifest or header files. We have sufficient
60+   ///    compiler arguments for these files to provide semantic editor functionality but we can't build them.
61+   package var  isBuildable :  Bool 
62+ 
5763  fileprivate  func  merging( _ other:  SourceFileInfo ? )  ->  SourceFileInfo  { 
5864    guard  let  other else  { 
5965      return  self 
6066    } 
6167    return  SourceFileInfo ( 
6268      targets:  targets. union ( other. targets) , 
6369      isPartOfRootProject:  other. isPartOfRootProject || isPartOfRootProject, 
64-       mayContainTests:  other. mayContainTests || mayContainTests
70+       mayContainTests:  other. mayContainTests || mayContainTests, 
71+       isBuildable:  other. isBuildable || isBuildable
6572    ) 
6673  } 
6774} 
@@ -327,11 +334,9 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
327334
328335  private  var  cachedTargetSources =  RequestCache < BuildTargetSourcesRequest > ( ) 
329336
330-   /// The parameters with which `SourceFilesAndDirectories` can be cached in `cachedSourceFilesAndDirectories`.
331-   private  struct  SourceFilesAndDirectoriesKey :  Hashable  { 
332-     let  includeNonBuildableFiles :  Bool 
333-     let  sourcesItems :  [ SourcesItem ] 
334-   } 
337+   /// `SourceFilesAndDirectories` is a global property that only gets reset when the build targets change and thus
338+   /// has no real key.
339+   private  struct  SourceFilesAndDirectoriesKey :  Hashable  { } 
335340
336341  private  struct  SourceFilesAndDirectories  { 
337342    /// The source files in the workspace, ie. all `SourceItem`s that have `kind == .file`.
@@ -678,7 +683,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
678683  package func  targets( for document:  DocumentURI )  async  ->  Set < BuildTargetIdentifier >  { 
679684    return  await  orLog ( " Getting targets for source file " )  { 
680685      var  result :  Set < BuildTargetIdentifier >  =  [ ] 
681-       let  filesAndDirectories  =  try await  sourceFilesAndDirectories ( includeNonBuildableFiles :   true ) 
686+       let  filesAndDirectories  =  try await  sourceFilesAndDirectories ( ) 
682687      if  let  targets =  filesAndDirectories. files [ document] ? . targets { 
683688        result. formUnion ( targets) 
684689      } 
@@ -1037,46 +1042,35 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
10371042  ///
10381043  /// - SeeAlso: Comment in `sourceFilesAndDirectories` for a definition of what `buildable` means.
10391044  package func  buildableSourceFiles( )  async  throws  ->  [ DocumentURI :  SourceFileInfo ]  { 
1040-     return  try await  sourceFilesAndDirectories ( includeNonBuildableFiles :   false ) . files
1045+     return  try await  sourceFilesAndDirectories ( ) . files. filter ( \ . value . isBuildable ) 
10411046  } 
10421047
10431048  /// Get all files and directories that are known to the build system, ie. that are returned by a `buildTarget/sources`
10441049  /// request for any target in the project.
10451050  ///
1046-   /// Source files returned here fall into two categories:
1047-   ///  - Buildable source files are files that can be built by the build system and that make sense to background index
1048-   ///  - Non-buildable source files include eg. the SwiftPM package manifest or header files. We have sufficient
1049-   ///    compiler arguments for these files to provide semantic editor functionality but we can't build them.
1050-   ///
1051-   /// `includeNonBuildableFiles` determines whether non-buildable files should be included.
1052-   private  func  sourceFilesAndDirectories( includeNonBuildableFiles:  Bool )  async  throws  ->  SourceFilesAndDirectories  { 
1053-     let  targets  =  try await  self . buildTargets ( ) 
1054-     let  sourcesItems  =  try await  self . sourceFiles ( in:  Set ( targets. keys) ) 
1055- 
1056-     let  key  =  SourceFilesAndDirectoriesKey ( 
1057-       includeNonBuildableFiles:  includeNonBuildableFiles, 
1058-       sourcesItems:  sourcesItems
1059-     ) 
1051+   /// - Important: This method returns both buildable and non-buildable source files. Callers need to check
1052+   /// `SourceFileInfo.isBuildable` if they are only interested in buildable source files.
1053+   private  func  sourceFilesAndDirectories( )  async  throws  ->  SourceFilesAndDirectories  { 
1054+     return  try await  cachedSourceFilesAndDirectories. get ( 
1055+       SourceFilesAndDirectoriesKey ( ) , 
1056+       isolation:  self 
1057+     )  {  key in 
1058+       let  targets  =  try await  self . buildTargets ( ) 
1059+       let  sourcesItems  =  try await  self . sourceFiles ( in:  Set ( targets. keys) ) 
10601060
1061-     return  try await  cachedSourceFilesAndDirectories. get ( key,  isolation:  self )  {  key in 
10621061      var  files :  [ DocumentURI :  SourceFileInfo ]  =  [ : ] 
10631062      var  directories :  [ DocumentURI :  ( pathComponents:  [ String ] ? ,  info:  SourceFileInfo ) ]  =  [ : ] 
1064-       for  sourcesItem  in  key . sourcesItems { 
1063+       for  sourcesItem  in  sourcesItems { 
10651064        let  target  =  targets [ sourcesItem. target] ? . target
10661065        let  isPartOfRootProject  =  !( target? . tags. contains ( . dependency)  ??  false ) 
10671066        let  mayContainTests  =  target? . tags. contains ( . test)  ??  true 
1068-         if  !key. includeNonBuildableFiles && ( target? . tags. contains ( . notBuildable)  ??  false )  { 
1069-           continue 
1070-         } 
1071- 
10721067        for  sourceItem  in  sourcesItem. sources { 
1073-           if  !key. includeNonBuildableFiles && sourceItem. sourceKitData? . isHeader ??  false  { 
1074-             continue 
1075-           } 
10761068          let  info  =  SourceFileInfo ( 
10771069            targets:  [ sourcesItem. target] , 
10781070            isPartOfRootProject:  isPartOfRootProject, 
1079-             mayContainTests:  mayContainTests
1071+             mayContainTests:  mayContainTests, 
1072+             isBuildable:  !( target? . tags. contains ( . notBuildable)  ??  false ) 
1073+               && !( sourceItem. sourceKitData? . isHeader ??  false ) 
10801074          ) 
10811075          switch  sourceItem. kind { 
10821076          case  . file: 
0 commit comments