@@ -17,7 +17,7 @@ public struct ModuleDependency: Hashable, Sendable, SerializableCodable {
1717 public let name : String
1818 public let accessLevel : AccessLevel
1919
20- public enum AccessLevel : String , Hashable , Sendable , CaseIterable , Codable , Serializable {
20+ public enum AccessLevel : String , Hashable , Sendable , CaseIterable , Codable , Serializable , Comparable {
2121 case Private = " private "
2222 case Package = " package "
2323 case Public = " public "
@@ -29,6 +29,18 @@ public struct ModuleDependency: Hashable, Sendable, SerializableCodable {
2929
3030 self = accessLevel
3131 }
32+
33+ // This allows easy merging of different access levels to always end up with the broadest one needed for a target.
34+ public static func < ( lhs: Self , rhs: Self ) -> Bool {
35+ switch lhs {
36+ case . Private:
37+ return true
38+ case . Public:
39+ return false
40+ case . Package:
41+ return rhs == . Public
42+ }
43+ }
3244 }
3345
3446 public init ( name: String , accessLevel: AccessLevel ) {
@@ -85,7 +97,7 @@ public struct ModuleDependenciesContext: Sendable, SerializableCodable {
8597 /// The compiler tracing information does not provide the import locations or whether they are public imports
8698 /// (which depends on whether the import is in an installed header file).
8799 /// If `files` is nil, the current toolchain does support the feature to trace imports.
88- public func computeMissingDependencies( files: [ Path ] ? ) -> [ ModuleDependency ] ? {
100+ public func computeMissingDependencies( files: [ Path ] ? ) -> [ ( ModuleDependency , importLocations : [ Diagnostic . Location ] ) ] ? {
89101 guard validate != . no else { return [ ] }
90102 guard let files else {
91103 return nil
@@ -108,67 +120,45 @@ public struct ModuleDependenciesContext: Sendable, SerializableCodable {
108120 ModuleDependency ( name: $0, accessLevel: . Private)
109121 } )
110122
111- return Array ( missingDeps)
123+ return missingDeps. map { ( $0 , [ ] ) }
112124 }
113125
114- /// Make diagnostics for missing module dependencies from Clang imports.
115- public func makeDiagnostics( missingDependencies: [ ModuleDependency ] ? ) -> [ Diagnostic ] {
116- guard let missingDependencies else {
117- return [ Diagnostic (
118- behavior: . warning,
119- location: . unknown,
120- data: DiagnosticData ( " The current toolchain does not support \( BuiltinMacros . VALIDATE_MODULE_DEPENDENCIES. name) " ) ) ]
121- }
122-
123- guard !missingDependencies. isEmpty else { return [ ] }
124-
125- let behavior : Diagnostic . Behavior = validate == . yesError ? . error : . warning
126-
127- let fixIt = fixItContext? . makeFixIt ( newModules: Array ( missingDependencies) )
128- let fixIts = fixIt. map { [ $0] } ?? [ ]
129-
130- let message = " Missing entries in \( BuiltinMacros . MODULE_DEPENDENCIES. name) : \( missingDependencies. map { $0. asBuildSettingEntryQuotedIfNeeded } . sorted ( ) . joined ( separator: " " ) ) "
131-
132- let location : Diagnostic . Location = fixIt. map {
133- Diagnostic . Location. path ( $0. sourceRange. path, line: $0. sourceRange. endLine, column: $0. sourceRange. endColumn)
134- } ?? Diagnostic . Location. buildSetting ( BuiltinMacros . MODULE_DEPENDENCIES)
135-
136- return [ Diagnostic (
137- behavior: behavior,
138- location: location,
139- data: DiagnosticData ( message) ,
140- fixIts: fixIts) ]
141- }
142-
143- /// Make diagnostics for missing module dependencies from Swift imports.
126+ /// Compute missing module dependencies from Swift imports.
144127 ///
145128 /// If `imports` is nil, the current toolchain does not support the features to gather imports.
146- public func makeDiagnostics ( imports: [ ( ModuleDependency , importLocations: [ Diagnostic . Location ] ) ] ? ) -> [ Diagnostic ] {
129+ public func computeMissingDependencies ( imports: [ ( ModuleDependency , importLocations: [ Diagnostic . Location ] ) ] ? ) -> [ ( ModuleDependency , importLocations : [ Diagnostic . Location ] ) ] ? {
147130 guard validate != . no else { return [ ] }
148131 guard let imports else {
149- return [ Diagnostic (
150- behavior: . warning,
151- location: . unknown,
152- data: DiagnosticData ( " The current toolchain does not support \( BuiltinMacros . VALIDATE_MODULE_DEPENDENCIES. name) " ) ) ]
132+ return nil
153133 }
154134
155- let missingDeps = imports. filter {
135+ return imports. filter {
156136 // ignore module deps without source locations, these are inserted by swift / swift-build and we should treat them as implementation details which we can track without needing the user to declare them
157137 if $0. importLocations. isEmpty { return false }
158138
159139 // TODO: if the difference is just the access modifier, we emit a new entry, but ultimately our fixit should update the existing entry or emit an error about a conflict
160140 if moduleDependencies. contains ( $0. 0 ) { return false }
161141 return true
162142 }
143+ }
144+
145+ /// Make diagnostics for missing module dependencies.
146+ public func makeDiagnostics( missingDependencies: [ ( ModuleDependency , importLocations: [ Diagnostic . Location ] ) ] ? ) -> [ Diagnostic ] {
147+ guard let missingDependencies else {
148+ return [ Diagnostic (
149+ behavior: . warning,
150+ location: . unknown,
151+ data: DiagnosticData ( " The current toolchain does not support \( BuiltinMacros . VALIDATE_MODULE_DEPENDENCIES. name) " ) ) ]
152+ }
163153
164- guard !missingDeps . isEmpty else { return [ ] }
154+ guard !missingDependencies . isEmpty else { return [ ] }
165155
166156 let behavior : Diagnostic . Behavior = validate == . yesError ? . error : . warning
167157
168- let fixIt = fixItContext? . makeFixIt ( newModules: missingDeps . map { $0. 0 } )
158+ let fixIt = fixItContext? . makeFixIt ( newModules: missingDependencies . map { $0. 0 } )
169159 let fixIts = fixIt. map { [ $0] } ?? [ ]
170160
171- let importDiags : [ Diagnostic ] = missingDeps
161+ let importDiags : [ Diagnostic ] = missingDependencies
172162 . flatMap { dep in
173163 dep. 1 . map {
174164 return Diagnostic (
@@ -179,7 +169,7 @@ public struct ModuleDependenciesContext: Sendable, SerializableCodable {
179169 }
180170 }
181171
182- let message = " Missing entries in \( BuiltinMacros . MODULE_DEPENDENCIES. name) : \( missingDeps . map { $0. 0 . asBuildSettingEntryQuotedIfNeeded } . sorted ( ) . joined ( separator: " " ) ) "
172+ let message = " Missing entries in \( BuiltinMacros . MODULE_DEPENDENCIES. name) : \( missingDependencies . map { $0. 0 . asBuildSettingEntryQuotedIfNeeded } . sorted ( ) . joined ( separator: " " ) ) "
183173
184174 let location : Diagnostic . Location = fixIt. map {
185175 Diagnostic . Location. path ( $0. sourceRange. path, line: $0. sourceRange. endLine, column: $0. sourceRange. endColumn)
0 commit comments