@@ -54,14 +54,21 @@ package struct SourceFileInfo: Sendable {
54
54
/// from non-test targets or files that don't actually contain any tests.
55
55
package var mayContainTests : Bool
56
56
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
+
57
63
fileprivate func merging( _ other: SourceFileInfo ? ) -> SourceFileInfo {
58
64
guard let other else {
59
65
return self
60
66
}
61
67
return SourceFileInfo (
62
68
targets: targets. union ( other. targets) ,
63
69
isPartOfRootProject: other. isPartOfRootProject || isPartOfRootProject,
64
- mayContainTests: other. mayContainTests || mayContainTests
70
+ mayContainTests: other. mayContainTests || mayContainTests,
71
+ isBuildable: other. isBuildable || isBuildable
65
72
)
66
73
}
67
74
}
@@ -327,11 +334,9 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
327
334
328
335
private var cachedTargetSources = RequestCache < BuildTargetSourcesRequest > ( )
329
336
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 { }
335
340
336
341
private struct SourceFilesAndDirectories {
337
342
/// The source files in the workspace, ie. all `SourceItem`s that have `kind == .file`.
@@ -678,7 +683,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
678
683
package func targets( for document: DocumentURI ) async -> Set < BuildTargetIdentifier > {
679
684
return await orLog ( " Getting targets for source file " ) {
680
685
var result : Set < BuildTargetIdentifier > = [ ]
681
- let filesAndDirectories = try await sourceFilesAndDirectories ( includeNonBuildableFiles : true )
686
+ let filesAndDirectories = try await sourceFilesAndDirectories ( )
682
687
if let targets = filesAndDirectories. files [ document] ? . targets {
683
688
result. formUnion ( targets)
684
689
}
@@ -1033,50 +1038,44 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
1033
1038
return response. items
1034
1039
}
1035
1040
1036
- /// Returns all source files in the project that can be built .
1041
+ /// Returns all source files in the project.
1037
1042
///
1038
1043
/// - SeeAlso: Comment in `sourceFilesAndDirectories` for a definition of what `buildable` means.
1039
- package func buildableSourceFiles( ) async throws -> [ DocumentURI : SourceFileInfo ] {
1040
- return try await sourceFilesAndDirectories ( includeNonBuildableFiles: false ) . files
1044
+ package func sourceFiles( includeNonBuildableFiles: Bool ) async throws -> [ DocumentURI : SourceFileInfo ] {
1045
+ let files = try await sourceFilesAndDirectories ( ) . files
1046
+ if includeNonBuildableFiles {
1047
+ return files
1048
+ } else {
1049
+ return files. filter ( \. value. isBuildable)
1050
+ }
1041
1051
}
1042
1052
1043
1053
/// Get all files and directories that are known to the build system, ie. that are returned by a `buildTarget/sources`
1044
1054
/// request for any target in the project.
1045
1055
///
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
- )
1056
+ /// - Important: This method returns both buildable and non-buildable source files. Callers need to check
1057
+ /// `SourceFileInfo.isBuildable` if they are only interested in buildable source files.
1058
+ private func sourceFilesAndDirectories( ) async throws -> SourceFilesAndDirectories {
1059
+ return try await cachedSourceFilesAndDirectories. get (
1060
+ SourceFilesAndDirectoriesKey ( ) ,
1061
+ isolation: self
1062
+ ) { key in
1063
+ let targets = try await self . buildTargets ( )
1064
+ let sourcesItems = try await self . sourceFiles ( in: Set ( targets. keys) )
1060
1065
1061
- return try await cachedSourceFilesAndDirectories. get ( key, isolation: self ) { key in
1062
1066
var files : [ DocumentURI : SourceFileInfo ] = [ : ]
1063
1067
var directories : [ DocumentURI : ( pathComponents: [ String ] ? , info: SourceFileInfo ) ] = [ : ]
1064
- for sourcesItem in key . sourcesItems {
1068
+ for sourcesItem in sourcesItems {
1065
1069
let target = targets [ sourcesItem. target] ? . target
1066
1070
let isPartOfRootProject = !( target? . tags. contains ( . dependency) ?? false )
1067
1071
let mayContainTests = target? . tags. contains ( . test) ?? true
1068
- if !key. includeNonBuildableFiles && ( target? . tags. contains ( . notBuildable) ?? false ) {
1069
- continue
1070
- }
1071
-
1072
1072
for sourceItem in sourcesItem. sources {
1073
- if !key. includeNonBuildableFiles && sourceItem. sourceKitData? . isHeader ?? false {
1074
- continue
1075
- }
1076
1073
let info = SourceFileInfo (
1077
1074
targets: [ sourcesItem. target] ,
1078
1075
isPartOfRootProject: isPartOfRootProject,
1079
- mayContainTests: mayContainTests
1076
+ mayContainTests: mayContainTests,
1077
+ isBuildable: !( target? . tags. contains ( . notBuildable) ?? false )
1078
+ && !( sourceItem. sourceKitData? . isHeader ?? false )
1080
1079
)
1081
1080
switch sourceItem. kind {
1082
1081
case . file:
@@ -1093,7 +1092,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
1093
1092
}
1094
1093
1095
1094
package func testFiles( ) async throws -> [ DocumentURI ] {
1096
- return try await buildableSourceFiles ( ) . compactMap { ( uri, info) -> DocumentURI ? in
1095
+ return try await sourceFiles ( includeNonBuildableFiles : false ) . compactMap { ( uri, info) -> DocumentURI ? in
1097
1096
guard info. isPartOfRootProject, info. mayContainTests else {
1098
1097
return nil
1099
1098
}
0 commit comments