@@ -13,19 +13,45 @@ import TSCBasic
13
13
import SwiftOptions
14
14
import Foundation
15
15
16
- @ _spi ( Testing ) public func isIosMacInterface ( _ path: VirtualPath ) throws -> Bool {
16
+ func getModuleFlags ( _ path: VirtualPath , _ ignorable : Bool ) throws -> [ String ] {
17
17
let data = try localFileSystem. readFileContents ( path) . cString
18
18
let myStrings = data. components ( separatedBy: . newlines)
19
- let prefix = " // swift-module-flags: "
19
+ let prefix = ignorable ? " // swift-module-flags-ignorable: " : " // swift-module-flags: "
20
20
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 " )
25
37
}
26
38
return false
27
39
}
28
40
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
+
29
55
enum ErrKind : String {
30
56
case err
31
57
case warn
@@ -35,7 +61,7 @@ enum ErrKind: String {
35
61
fileprivate func getErrKind( _ content: String ) -> ErrKind {
36
62
if content. contains ( " error: " ) {
37
63
return . err
38
- } else if content. contains ( " warning: " ) {
64
+ } else if content. contains ( " warning: " ) {
39
65
return . warn
40
66
} else {
41
67
return . note
@@ -250,6 +276,12 @@ public struct PrebuiltModuleInput {
250
276
}
251
277
}
252
278
279
+ public enum AdopterIssueKind : String , Codable {
280
+ case libraryEvolutionDisabled
281
+ case libraryLevelMissing
282
+ case libraryLevelWrong
283
+ }
284
+
253
285
public class SwiftAdopter : Codable {
254
286
public let name : String
255
287
public let moduleDir : String
@@ -260,6 +292,7 @@ public class SwiftAdopter: Codable {
260
292
public let isPrivate : Bool
261
293
public let hasCompatibilityHeader : Bool
262
294
public let isMixed : Bool
295
+ public let issues : [ AdopterIssueKind ] ?
263
296
init ( _ name: String , _ moduleDir: AbsolutePath , _ hasInterface: [ AbsolutePath ] , _ hasModule: [ AbsolutePath ] ) throws {
264
297
self . name = name
265
298
self . moduleDir = SwiftAdopter . relativeToSDK ( moduleDir)
@@ -271,6 +304,27 @@ public class SwiftAdopter: Codable {
271
304
let headers = try SwiftAdopter . collectHeaderNames ( moduleDir. parentDirectory. parentDirectory)
272
305
self . hasCompatibilityHeader = headers. contains { $0 == " \( name) -Swift.h " }
273
306
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
274
328
}
275
329
276
330
static func collectHeaderNames( _ headersIn: AbsolutePath ) throws -> [ String ] {
0 commit comments