@@ -13,19 +13,45 @@ import TSCBasic
1313import SwiftOptions
1414import Foundation
1515
16- @ _spi ( Testing ) public func isIosMacInterface ( _ path: VirtualPath ) throws -> Bool {
16+ func getModuleFlags ( _ path: VirtualPath , _ ignorable : Bool ) throws -> [ String ] {
1717 let data = try localFileSystem. readFileContents ( path) . cString
1818 let myStrings = data. components ( separatedBy: . newlines)
19- let prefix = " // swift-module-flags: "
19+ let prefix = ignorable ? " // swift-module-flags-ignorable: " : " // swift-module-flags: "
2020 if let argLine = myStrings. first ( where: { $0. hasPrefix ( prefix) } ) {
21- let args = argLine. dropFirst ( prefix. count) . components ( separatedBy: " " )
22- if let idx = args. firstIndex ( of: " -target " ) , idx + 1 < args. count {
23- return args [ idx + 1 ] . contains ( " macabi " )
24- }
21+ return argLine. dropFirst ( prefix. count) . components ( separatedBy: " " )
22+ }
23+ return [ ]
24+ }
25+
26+ @_spi ( Testing) public func getAllModuleFlags( _ path: VirtualPath ) throws -> [ String ] {
27+ var allFlags : [ String ] = [ ]
28+ allFlags. append ( contentsOf: try getModuleFlags ( path, true ) )
29+ allFlags. append ( contentsOf: try getModuleFlags ( path, false ) )
30+ return allFlags;
31+ }
32+
33+ @_spi ( Testing) public func isIosMacInterface( _ path: VirtualPath ) throws -> Bool {
34+ let args = try getAllModuleFlags ( path)
35+ if let idx = args. firstIndex ( of: " -target " ) , idx + 1 < args. count {
36+ return args [ idx + 1 ] . contains ( " macabi " )
2537 }
2638 return false
2739}
2840
41+ @_spi ( Testing) public enum LibraryLevel : String , Codable {
42+ case api
43+ case spi
44+ case unknown
45+ case unspecified
46+ }
47+
48+ @_spi ( Testing) public func getLibraryLevel( _ flags: [ String ] ) throws -> LibraryLevel {
49+ if let idx = flags. firstIndex ( of: " -library-level " ) , idx + 1 < flags. count {
50+ return LibraryLevel ( rawValue: flags [ idx + 1 ] ) ?? . unknown
51+ }
52+ return . unspecified
53+ }
54+
2955enum ErrKind : String {
3056 case err
3157 case warn
@@ -35,7 +61,7 @@ enum ErrKind: String {
3561fileprivate func getErrKind( _ content: String ) -> ErrKind {
3662 if content. contains ( " error: " ) {
3763 return . err
38- } else if content. contains ( " warning: " ) {
64+ } else if content. contains ( " warning: " ) {
3965 return . warn
4066 } else {
4167 return . note
@@ -250,6 +276,12 @@ public struct PrebuiltModuleInput {
250276 }
251277}
252278
279+ public enum AdopterIssueKind : String , Codable {
280+ case libraryEvolutionDisabled
281+ case libraryLevelMissing
282+ case libraryLevelWrong
283+ }
284+
253285public class SwiftAdopter : Codable {
254286 public let name : String
255287 public let moduleDir : String
@@ -260,6 +292,7 @@ public class SwiftAdopter: Codable {
260292 public let isPrivate : Bool
261293 public let hasCompatibilityHeader : Bool
262294 public let isMixed : Bool
295+ public let issues : [ AdopterIssueKind ] ?
263296 init ( _ name: String , _ moduleDir: AbsolutePath , _ hasInterface: [ AbsolutePath ] , _ hasModule: [ AbsolutePath ] ) throws {
264297 self . name = name
265298 self . moduleDir = SwiftAdopter . relativeToSDK ( moduleDir)
@@ -271,6 +304,27 @@ public class SwiftAdopter: Codable {
271304 let headers = try SwiftAdopter . collectHeaderNames ( moduleDir. parentDirectory. parentDirectory)
272305 self . hasCompatibilityHeader = headers. contains { $0 == " \( name) -Swift.h " }
273306 self . isMixed = headers. contains { $0 != " \( name) -Swift.h " }
307+ self . issues = try Self . collectModuleIssues ( hasInterface. first, self . isPrivate)
308+ }
309+
310+ static func collectModuleIssues( _ interface: AbsolutePath ? , _ isPrivate: Bool ) throws -> [ AdopterIssueKind ] ? {
311+ guard let interface = interface else { return nil }
312+ var issues : [ AdopterIssueKind ] = [ ]
313+ let flags = try getAllModuleFlags ( VirtualPath . absolute ( interface) )
314+ let libLevel = try getLibraryLevel ( flags)
315+ if libLevel == . unspecified {
316+ issues. append ( . libraryLevelMissing)
317+ }
318+ if libLevel == . spi && !isPrivate {
319+ issues. append ( . libraryLevelWrong)
320+ }
321+ if libLevel == . api && isPrivate {
322+ issues. append ( . libraryLevelWrong)
323+ }
324+ if !flags. contains ( " -enable-library-evolution " ) {
325+ issues. append ( . libraryEvolutionDisabled)
326+ }
327+ return issues. isEmpty ? nil : issues
274328 }
275329
276330 static func collectHeaderNames( _ headersIn: AbsolutePath ) throws -> [ String ] {
0 commit comments