From e2ea4c5de8307d623658b7a93cae20d67e71227b Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Sat, 7 Jun 2025 10:49:36 -0700 Subject: [PATCH] Replace bespoke availability system Removes the script based availability system with the experimental availability macro feature. --- Package.swift | 29 ++++- Sources/System/Errno.swift | 12 +- Sources/System/FileDescriptor.swift | 18 +-- Sources/System/FileHelpers.swift | 2 +- Sources/System/FileOperations.swift | 20 +-- Sources/System/FilePath/FilePath.swift | 8 +- .../FilePath/FilePathComponentView.swift | 16 +-- .../System/FilePath/FilePathComponents.swift | 28 ++--- Sources/System/FilePath/FilePathParsing.swift | 16 +-- Sources/System/FilePath/FilePathString.swift | 34 ++--- Sources/System/FilePath/FilePathSyntax.swift | 16 +-- Sources/System/FilePermissions.swift | 4 +- Sources/System/Internals/CInterop.swift | 4 +- Sources/System/MachPort.swift | 32 ++--- Sources/System/PlatformString.swift | 6 +- Sources/System/Util.swift | 8 +- Tests/SystemTests/ErrnoTest.swift | 2 +- Tests/SystemTests/FileOperationsTest.swift | 2 +- .../FilePathComponentsTest.swift | 4 +- .../FilePathTests/FilePathDecodable.swift | 2 +- .../FilePathTests/FilePathExtras.swift | 4 +- .../FilePathTests/FilePathParsingTest.swift | 2 +- .../FilePathTests/FilePathSyntaxTest.swift | 6 +- .../FilePathTests/FilePathTest.swift | 4 +- Tests/SystemTests/FileTypesTest.swift | 4 +- Tests/SystemTests/MachPortTests.swift | 2 +- Tests/SystemTests/MockingTest.swift | 2 +- Utilities/expand-availability.py | 117 ------------------ 28 files changed, 157 insertions(+), 247 deletions(-) delete mode 100755 Utilities/expand-availability.py diff --git a/Package.swift b/Package.swift index b71ade66..1ba635fa 100644 --- a/Package.swift +++ b/Package.swift @@ -16,13 +16,40 @@ let cSettings: [CSetting] = [ .define("_CRT_SECURE_NO_WARNINGS", .when(platforms: [.windows])), ] +let availability = [ + ("0.0.1", "macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0"), + ("0.0.2", "macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0"), + // FIXME: 0.0.3 + ("1.1.0", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"), + // FIXME: 1.1.1 + ("1.2.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), + // FIXME: 1.2.1 + ("1.3.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), + // FIXME: 1.3.1 + // FIXME: 1.3.2 + ("1.4.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), + // FIXME: 1.4.1 + // FIXME: 1.4.2 + // FIXME: 1.5.0 +] + let swiftSettings: [SwiftSetting] = [ .define( "SYSTEM_PACKAGE_DARWIN", .when(platforms: [.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .visionOS])), .define("SYSTEM_PACKAGE"), .define("ENABLE_MOCKING", .when(configuration: .debug)), -] +] + availability.map { (version, osAvailability) -> SwiftSetting in + #if SYSTEM_PACKAGE + // Matches default SwiftPM availability + let availability = "macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, visionOS 1.0" + #else + let availability = osAvailability + #endif + + return .enableExperimentalFeature( + "AvailabilityMacro=System \(version):\(availability)") +} let package = Package( name: "swift-system", diff --git a/Sources/System/Errno.swift b/Sources/System/Errno.swift index e88b96d9..43b46af5 100644 --- a/Sources/System/Errno.swift +++ b/Sources/System/Errno.swift @@ -10,7 +10,7 @@ /// An error number used by system calls to communicate what kind of error /// occurred. @frozen -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public struct Errno: RawRepresentable, Error, Hashable, Codable { /// The raw C error number. @_alwaysEmitIntoClient @@ -1391,7 +1391,7 @@ public struct Errno: RawRepresentable, Error, Hashable, Codable { } // Constants defined in header but not man page -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno { /// Operation would block. /// @@ -1520,7 +1520,7 @@ extension Errno { #endif } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno { // TODO: We want to provide safe access to `errno`, but we need a // release-barrier to do so. @@ -1535,14 +1535,14 @@ extension Errno { } // Use "hidden" entry points for `NSError` bridging -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno { public var _code: Int { Int(rawValue) } public var _domain: String { "NSPOSIXErrorDomain" } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of the most recent error /// returned by a system call. @@ -1562,7 +1562,7 @@ extension Errno: CustomStringConvertible, CustomDebugStringConvertible { public var debugDescription: String { self.description } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno { @_alwaysEmitIntoClient public static func ~=(_ lhs: Errno, _ rhs: Error) -> Bool { diff --git a/Sources/System/FileDescriptor.swift b/Sources/System/FileDescriptor.swift index c9953e8b..d5f5883b 100644 --- a/Sources/System/FileDescriptor.swift +++ b/Sources/System/FileDescriptor.swift @@ -14,7 +14,7 @@ /// of `FileDescriptor` values, /// in the same way as you manage a raw C file handle. @frozen -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public struct FileDescriptor: RawRepresentable, Hashable, Codable { /// The raw C file handle. @_alwaysEmitIntoClient @@ -26,7 +26,7 @@ public struct FileDescriptor: RawRepresentable, Hashable, Codable { } // Standard file descriptors. -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor { /// The standard input file descriptor, with a numeric value of 0. @_alwaysEmitIntoClient @@ -41,11 +41,11 @@ extension FileDescriptor { public static var standardError: FileDescriptor { .init(rawValue: 2) } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor { /// The desired read and write access for a newly opened file. @frozen - @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + @available(System 0.0.1, *) public struct AccessMode: RawRepresentable, Sendable, Hashable, Codable { /// The raw C access mode. @_alwaysEmitIntoClient @@ -88,7 +88,7 @@ extension FileDescriptor { /// Options that specify behavior for a newly-opened file. @frozen - @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + @available(System 0.0.1, *) public struct OpenOptions: OptionSet, Sendable, Hashable, Codable { /// The raw C options. @_alwaysEmitIntoClient @@ -326,7 +326,7 @@ extension FileDescriptor { /// Options for specifying what a file descriptor's offset is relative to. @frozen - @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + @available(System 0.0.1, *) public struct SeekOrigin: RawRepresentable, Sendable, Hashable, Codable { /// The raw C value. @_alwaysEmitIntoClient @@ -402,7 +402,7 @@ extension FileDescriptor { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor.AccessMode : CustomStringConvertible, CustomDebugStringConvertible { @@ -421,7 +421,7 @@ extension FileDescriptor.AccessMode public var debugDescription: String { self.description } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor.SeekOrigin : CustomStringConvertible, CustomDebugStringConvertible { @@ -444,7 +444,7 @@ extension FileDescriptor.SeekOrigin public var debugDescription: String { self.description } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor.OpenOptions : CustomStringConvertible, CustomDebugStringConvertible { diff --git a/Sources/System/FileHelpers.swift b/Sources/System/FileHelpers.swift index 2ddb0729..5b082766 100644 --- a/Sources/System/FileHelpers.swift +++ b/Sources/System/FileHelpers.swift @@ -7,7 +7,7 @@ See https://swift.org/LICENSE.txt for license information */ -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor { /// Runs a closure and then closes the file descriptor, even if an error occurs. /// diff --git a/Sources/System/FileOperations.swift b/Sources/System/FileOperations.swift index fc9fc932..8c6c7fa5 100644 --- a/Sources/System/FileOperations.swift +++ b/Sources/System/FileOperations.swift @@ -7,7 +7,7 @@ See https://swift.org/LICENSE.txt for license information */ -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor { /// Opens or creates a file for reading or writing. /// @@ -368,7 +368,7 @@ extension FileDescriptor { } #if !os(WASI) -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FileDescriptor { /// Duplicates this file descriptor and return the newly created copy. /// @@ -398,7 +398,7 @@ extension FileDescriptor { /// /// The corresponding C functions are `dup` and `dup2`. @_alwaysEmitIntoClient - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public func duplicate( as target: FileDescriptor? = nil, retryOnInterrupt: Bool = true @@ -406,7 +406,7 @@ extension FileDescriptor { try _duplicate(as: target, retryOnInterrupt: retryOnInterrupt).get() } - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) @usableFromInline internal func _duplicate( as target: FileDescriptor?, @@ -435,7 +435,7 @@ extension FileDescriptor { #endif #if !os(WASI) -@available(/*System 1.1.0: macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4*/iOS 8, *) +@available(System 1.1.0, *) extension FileDescriptor { /// Creates a unidirectional data channel, which can be used for interprocess communication. /// @@ -443,12 +443,12 @@ extension FileDescriptor { /// /// The corresponding C function is `pipe`. @_alwaysEmitIntoClient - @available(/*System 1.1.0: macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4*/iOS 8, *) + @available(System 1.1.0, *) public static func pipe() throws -> (readEnd: FileDescriptor, writeEnd: FileDescriptor) { try _pipe().get() } - @available(/*System 1.1.0: macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4*/iOS 8, *) + @available(System 1.1.0, *) @usableFromInline internal static func _pipe() -> Result<(readEnd: FileDescriptor, writeEnd: FileDescriptor), Errno> { var fds: (Int32, Int32) = (-1, -1) @@ -463,7 +463,7 @@ extension FileDescriptor { } #endif -@available(/*System 1.2.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.2.0, *) extension FileDescriptor { /// Truncates or extends the file referenced by this file descriptor. /// @@ -485,7 +485,7 @@ extension FileDescriptor { /// associated with the file. /// /// The corresponding C function is `ftruncate`. - @available(/*System 1.2.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.2.0, *) @_alwaysEmitIntoClient public func resize( to newSize: Int64, @@ -497,7 +497,7 @@ extension FileDescriptor { ).get() } - @available(/*System 1.2.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.2.0, *) @usableFromInline internal func _resize( to newSize: Int64, diff --git a/Sources/System/FilePath/FilePath.swift b/Sources/System/FilePath/FilePath.swift index f056759d..b27d053a 100644 --- a/Sources/System/FilePath/FilePath.swift +++ b/Sources/System/FilePath/FilePath.swift @@ -37,7 +37,7 @@ /// However, the rules for path equivalence /// are file-system–specific and have additional considerations /// like case insensitivity, Unicode normalization, and symbolic links. -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public struct FilePath: Sendable { // TODO(docs): Section on all the new syntactic operations, lexical normalization, decomposition, // components, etc. @@ -59,16 +59,16 @@ public struct FilePath: Sendable { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { /// The length of the file path, excluding the null terminator. public var length: Int { _storage.length } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: Hashable {} -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: Codable { // Encoder is synthesized; it probably should have been explicit and used // a single-value container, but making that change now is somewhat risky. diff --git a/Sources/System/FilePath/FilePathComponentView.swift b/Sources/System/FilePath/FilePathComponentView.swift index 39381b4b..be176305 100644 --- a/Sources/System/FilePath/FilePathComponentView.swift +++ b/Sources/System/FilePath/FilePathComponentView.swift @@ -9,7 +9,7 @@ // MARK: - API -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// A bidirectional, range replaceable collection of the non-root components /// that make up a file path. @@ -28,7 +28,7 @@ extension FilePath { /// /// path.components.removeAll { $0.kind == .currentDirectory } /// // path is "/home/username/bin/scripts/tree" - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public struct ComponentView: Sendable { internal var _path: FilePath internal var _start: SystemString.Index @@ -64,11 +64,11 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView: BidirectionalCollection { public typealias Element = FilePath.Component - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public struct Index: Sendable, Comparable, Hashable { internal typealias Storage = SystemString.Index @@ -100,7 +100,7 @@ extension FilePath.ComponentView: BidirectionalCollection { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView: RangeReplaceableCollection { public init() { self.init(FilePath()) @@ -150,7 +150,7 @@ extension FilePath.ComponentView: RangeReplaceableCollection { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Create a file path from a root and a collection of components. public init( @@ -179,7 +179,7 @@ extension FilePath { // MARK: - Internals -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView: _PathSlice { internal var _range: Range { _start ..< _path._storage.endIndex @@ -192,7 +192,7 @@ extension FilePath.ComponentView: _PathSlice { // MARK: - Invariants -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView { internal func _invariantCheck() { #if DEBUG diff --git a/Sources/System/FilePath/FilePathComponents.swift b/Sources/System/FilePath/FilePathComponents.swift index b304a0a7..f2352617 100644 --- a/Sources/System/FilePath/FilePathComponents.swift +++ b/Sources/System/FilePath/FilePathComponents.swift @@ -9,7 +9,7 @@ // MARK: - API -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Represents a root of a file path. /// @@ -28,7 +28,7 @@ extension FilePath { /// * `\\server\share\` /// * `\\?\UNC\server\share\` /// * `\\?\Volume{12345678-abcd-1111-2222-123445789abc}\` - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public struct Root: Sendable { internal var _path: FilePath internal var _rootEnd: SystemString.Index @@ -55,7 +55,7 @@ extension FilePath { /// file.kind == .regular // true /// file.extension // "txt" /// path.append(file) // path is "/tmp/foo.txt" - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public struct Component: Sendable { internal var _path: FilePath internal var _range: Range @@ -74,13 +74,13 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { /// Whether a component is a regular file or directory name, or a special /// directory `.` or `..` @frozen - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public enum Kind: Sendable { /// The special directory `.`, representing the current directory. case currentDirectory @@ -100,7 +100,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { // TODO: Windows analysis APIs } @@ -186,17 +186,17 @@ extension _PathSlice { internal var _storage: SystemString { _path._storage } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component: _PathSlice { } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root: _PathSlice { internal var _range: Range { (..<_rootEnd).relative(to: _path._storage) } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: _PlatformStringable { func _withPlatformString(_ body: (UnsafePointer) throws -> Result) rethrows -> Result { try _storage.withPlatformString(body) @@ -208,7 +208,7 @@ extension FilePath: _PlatformStringable { } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { // The index of the `.` denoting an extension internal func _extensionIndex() -> SystemString.Index? { @@ -237,7 +237,7 @@ internal func _makeExtension(_ ext: String) -> SystemString { return result } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { internal init?(_ str: SystemString) { // FIXME: explicit null root? Or something else? @@ -250,7 +250,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { internal init?(_ str: SystemString) { // FIXME: explicit null root? Or something else? @@ -265,7 +265,7 @@ extension FilePath.Root { // MARK: - Invariants -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { // TODO: ensure this all gets easily optimized away in release... internal func _invariantCheck() { @@ -278,7 +278,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { internal func _invariantCheck() { #if DEBUG diff --git a/Sources/System/FilePath/FilePathParsing.swift b/Sources/System/FilePath/FilePathParsing.swift index c31e6a5b..f372dd67 100644 --- a/Sources/System/FilePath/FilePathParsing.swift +++ b/Sources/System/FilePath/FilePathParsing.swift @@ -116,7 +116,7 @@ extension SystemString { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal mutating func _removeTrailingSeparator() { _storage._removeTrailingSeparator() @@ -197,7 +197,7 @@ extension SystemString { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal var _relativeStart: SystemString.Index { _storage._relativePathStart @@ -209,7 +209,7 @@ extension FilePath { // Parse separators -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal typealias _Index = SystemString.Index @@ -273,7 +273,7 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView { // TODO: Store this... internal var _relativeStart: SystemString.Index { @@ -298,7 +298,7 @@ extension SystemString { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { // Asserting self is a root, returns whether this is an // absolute root. @@ -323,7 +323,7 @@ extension FilePath.Root { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal var _portableDescription: String { guard _windowsPaths else { return description } @@ -345,7 +345,7 @@ internal var _windowsPaths: Bool { #endif } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { // Whether we should add a separator when doing an append internal var _needsSeparatorForAppend: Bool { @@ -373,7 +373,7 @@ extension FilePath { } // MARK: - Invariants -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal func _invariantsSatisfied() -> Bool { var normal = self diff --git a/Sources/System/FilePath/FilePathString.swift b/Sources/System/FilePath/FilePathString.swift index 4fe9c1fd..45f79c8a 100644 --- a/Sources/System/FilePath/FilePathString.swift +++ b/Sources/System/FilePath/FilePathString.swift @@ -9,7 +9,7 @@ // MARK: - Platform string -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Creates a file path by copying bytes from a null-terminated platform /// string. @@ -109,7 +109,7 @@ extension FilePath { #endif } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { /// Creates a file path component by copying bytes from a null-terminated /// platform string. @@ -198,7 +198,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { /// Creates a file path root by copying bytes from a null-terminated platform /// string. @@ -287,7 +287,7 @@ extension FilePath.Root { // MARK: - String literals -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: ExpressibleByStringLiteral { /// Creates a file path from a string literal. /// @@ -306,7 +306,7 @@ extension FilePath: ExpressibleByStringLiteral { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component: ExpressibleByStringLiteral { /// Create a file path component from a string literal. /// @@ -331,7 +331,7 @@ extension FilePath.Component: ExpressibleByStringLiteral { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root: ExpressibleByStringLiteral { /// Create a file path root from a string literal. /// @@ -356,7 +356,7 @@ extension FilePath.Root: ExpressibleByStringLiteral { // MARK: - Printing and dumping -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of the file path. /// @@ -372,7 +372,7 @@ extension FilePath: CustomStringConvertible, CustomDebugStringConvertible { public var debugDescription: String { description.debugDescription } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of the path component. @@ -389,7 +389,7 @@ extension FilePath.Component: CustomStringConvertible, CustomDebugStringConverti public var debugDescription: String { description.debugDescription } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of the path root. @@ -409,7 +409,7 @@ extension FilePath.Root: CustomStringConvertible, CustomDebugStringConvertible { // MARK: - Convenience helpers // Convenience helpers -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Creates a string by interpreting the path’s content as UTF-8 on Unix /// and UTF-16 on Windows. @@ -420,7 +420,7 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { /// Creates a string by interpreting the component’s content as UTF-8 on Unix /// and UTF-16 on Windows. @@ -431,7 +431,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { /// On Unix, this returns `"/"`. /// @@ -445,7 +445,7 @@ extension FilePath.Root { // MARK: - Decoding and validating -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension String { /// Creates a string by interpreting the file path's content as UTF-8 on Unix /// and UTF-16 on Windows. @@ -475,7 +475,7 @@ extension String { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension String { /// Creates a string by interpreting the path component's content as UTF-8 on /// Unix and UTF-16 on Windows. @@ -505,7 +505,7 @@ extension String { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension String { /// On Unix, creates the string `"/"` /// @@ -558,7 +558,7 @@ extension String { // MARK: - Deprecations -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension String { @available(*, deprecated, renamed: "init(decoding:)") public init(_ path: FilePath) { self.init(decoding: path) } @@ -568,7 +568,7 @@ extension String { } #if !os(Windows) -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { /// For backwards compatibility only. This initializer is equivalent to /// the preferred `FilePath(platformString:)`. diff --git a/Sources/System/FilePath/FilePathSyntax.swift b/Sources/System/FilePath/FilePathSyntax.swift index 1c3fc097..eb1f25df 100644 --- a/Sources/System/FilePath/FilePathSyntax.swift +++ b/Sources/System/FilePath/FilePathSyntax.swift @@ -9,7 +9,7 @@ // MARK: - Query API -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Returns true if this path uniquely identifies the location of /// a file without reference to an additional starting location. @@ -99,7 +99,7 @@ extension FilePath { } // MARK: - Decompose a path -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Returns the root of a path if there is one, otherwise `nil`. /// @@ -182,7 +182,7 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Returns the final component of the path. /// Returns `nil` if the path is empty or only contains a root. @@ -252,7 +252,7 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { /// The extension of this file or directory component. /// @@ -283,7 +283,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// The extension of the file or directory last component. @@ -349,7 +349,7 @@ extension FilePath { } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Whether the path is in lexical-normal form, that is `.` and `..` /// components have been collapsed lexically (i.e. without following @@ -430,7 +430,7 @@ extension FilePath { } // Modification and concatenation API -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { // TODO(Windows docs): example with roots /// If `prefix` is a prefix of `self`, removes it and returns `true`. @@ -583,7 +583,7 @@ extension FilePath { } // MARK - Renamed -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { @available(*, unavailable, renamed: "removingLastComponent()") public var dirname: FilePath { removingLastComponent() } diff --git a/Sources/System/FilePermissions.swift b/Sources/System/FilePermissions.swift index 918246ef..f849a997 100644 --- a/Sources/System/FilePermissions.swift +++ b/Sources/System/FilePermissions.swift @@ -17,7 +17,7 @@ /// let perms = FilePermissions(rawValue: 0o644) /// perms == [.ownerReadWrite, .groupRead, .otherRead] // true @frozen -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public struct FilePermissions: OptionSet, Sendable, Hashable, Codable { /// The raw C file permissions. @_alwaysEmitIntoClient @@ -132,7 +132,7 @@ public struct FilePermissions: OptionSet, Sendable, Hashable, Codable { public static var saveText: FilePermissions { .init(rawValue: 0o1000) } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePermissions : CustomStringConvertible, CustomDebugStringConvertible { diff --git a/Sources/System/Internals/CInterop.swift b/Sources/System/Internals/CInterop.swift index 80d37d05..b6de1233 100644 --- a/Sources/System/Internals/CInterop.swift +++ b/Sources/System/Internals/CInterop.swift @@ -37,12 +37,12 @@ import Bionic public typealias CModeT = CInt #else /// The C `mode_t` type. -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public typealias CModeT = mode_t #endif /// A namespace for C and platform types -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) public enum CInterop { #if os(Windows) public typealias Mode = CInt diff --git a/Sources/System/MachPort.swift b/Sources/System/MachPort.swift index 8cc05096..313f6c28 100644 --- a/Sources/System/MachPort.swift +++ b/Sources/System/MachPort.swift @@ -11,10 +11,10 @@ import Darwin.Mach -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) public protocol MachPortRight {} -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) @inlinable internal func _machPrecondition( file: StaticString = #file, @@ -26,10 +26,10 @@ internal func _machPrecondition( precondition(kr == expected, file: file, line: line) } -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) @frozen public enum Mach { - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public struct Port: ~Copyable { @usableFromInline internal var _name: mach_port_name_t @@ -133,7 +133,7 @@ public enum Mach { public struct SendOnceRight: MachPortRight {} } -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) extension Mach.Port where RightType == Mach.ReceiveRight { /// Transfer ownership of an existing, unmanaged, but already guarded, /// Mach port right into a Mach.Port by name. @@ -158,7 +158,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// This initializer will abort if the right could not be created. /// Callers may assert that a valid right is always returned. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public init() { var storage: mach_port_name_t = mach_port_name_t(MACH_PORT_NULL) _machPrecondition( @@ -181,7 +181,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// After this function completes, the Mach.Port is destroyed and no longer /// usable. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public consuming func relinquish( ) -> (name: mach_port_name_t, context: mach_port_context_t) { let destructured = (name: _name, context: _context) @@ -204,7 +204,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// Mach.ReceiveRights. Use relinquish() to avoid the syscall and extract /// the context value along with the port name. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public consuming func unguardAndRelinquish() -> mach_port_name_t { let (name, context) = self.relinquish() _machPrecondition(mach_port_unguard(mach_task_self_, name, context)) @@ -221,7 +221,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// The body block may optionally return something, which will then be /// returned to the caller of withBorrowedName. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public func withBorrowedName( body: (mach_port_name_t, mach_port_context_t) -> ReturnType ) -> ReturnType { @@ -235,7 +235,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// This function will abort if the right could not be created. /// Callers may assert that a valid right is always returned. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public func makeSendOnceRight() -> Mach.Port { // send once rights do not coalesce var newRight: mach_port_name_t = mach_port_name_t(MACH_PORT_NULL) @@ -264,7 +264,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// This function will abort if the right could not be created. /// Callers may assert that a valid right is always returned. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public func makeSendRight() -> Mach.Port { let how = MACH_MSG_TYPE_MAKE_SEND @@ -282,7 +282,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// /// Each get/set of this property makes a syscall. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public var makeSendCount: mach_port_mscount_t { get { var status: mach_port_status = mach_port_status() @@ -311,7 +311,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { } } -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) extension Mach.Port where RightType == Mach.SendRight { /// Transfer ownership of the underlying port right to the caller. /// @@ -337,7 +337,7 @@ extension Mach.Port where RightType == Mach.SendRight { /// receiving side has been deallocated, then copySendRight() will throw /// a Mach.PortRightError.deadName error. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public func copySendRight() throws -> Mach.Port { let how = MACH_MSG_TYPE_COPY_SEND @@ -354,7 +354,7 @@ extension Mach.Port where RightType == Mach.SendRight { } } -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) extension Mach.Port where RightType == Mach.SendOnceRight { /// Transfer ownership of the underlying port right to the caller. /// @@ -366,7 +366,7 @@ extension Mach.Port where RightType == Mach.SendOnceRight { /// After this function completes, the Mach.Port is destroyed and no longer /// usable. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public consuming func relinquish() -> mach_port_name_t { let name = _name discard self diff --git a/Sources/System/PlatformString.swift b/Sources/System/PlatformString.swift index 664a6089..7b8fd90c 100644 --- a/Sources/System/PlatformString.swift +++ b/Sources/System/PlatformString.swift @@ -7,7 +7,7 @@ See https://swift.org/LICENSE.txt for license information */ -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension String { /// Creates a string by interpreting the null-terminated platform string as /// UTF-8 on Unix and UTF-16 on Windows. @@ -165,7 +165,7 @@ extension String { } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension CInterop.PlatformChar { internal var _platformCodeUnit: CInterop.PlatformUnicodeEncoding.CodeUnit { #if os(Windows) @@ -176,7 +176,7 @@ extension CInterop.PlatformChar { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension CInterop.PlatformUnicodeEncoding.CodeUnit { internal var _platformChar: CInterop.PlatformChar { #if os(Windows) diff --git a/Sources/System/Util.swift b/Sources/System/Util.swift index 3a8df9ac..e4832ac5 100644 --- a/Sources/System/Util.swift +++ b/Sources/System/Util.swift @@ -8,21 +8,21 @@ */ // Results in errno if i == -1 -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) private func valueOrErrno( _ i: I ) -> Result { i == -1 ? .failure(Errno.current) : .success(i) } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) private func nothingOrErrno( _ i: I ) -> Result<(), Errno> { valueOrErrno(i).map { _ in () } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) internal func valueOrErrno( retryOnInterrupt: Bool, _ f: () -> I ) -> Result { @@ -36,7 +36,7 @@ internal func valueOrErrno( } while true } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) internal func nothingOrErrno( retryOnInterrupt: Bool, _ f: () -> I ) -> Result<(), Errno> { diff --git a/Tests/SystemTests/ErrnoTest.swift b/Tests/SystemTests/ErrnoTest.swift index da09657e..6e50bfb9 100644 --- a/Tests/SystemTests/ErrnoTest.swift +++ b/Tests/SystemTests/ErrnoTest.swift @@ -19,7 +19,7 @@ import System import WinSDK #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class ErrnoTest: XCTestCase { func testConstants() { XCTAssert(EPERM == Errno.notPermitted.rawValue) diff --git a/Tests/SystemTests/FileOperationsTest.swift b/Tests/SystemTests/FileOperationsTest.swift index 18adde37..2d78a616 100644 --- a/Tests/SystemTests/FileOperationsTest.swift +++ b/Tests/SystemTests/FileOperationsTest.swift @@ -18,7 +18,7 @@ import XCTest import Android #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class FileOperationsTest: XCTestCase { func testSyscalls() { let fd = FileDescriptor(rawValue: 1) diff --git a/Tests/SystemTests/FilePathTests/FilePathComponentsTest.swift b/Tests/SystemTests/FilePathTests/FilePathComponentsTest.swift index e816bb5a..d72d59a2 100644 --- a/Tests/SystemTests/FilePathTests/FilePathComponentsTest.swift +++ b/Tests/SystemTests/FilePathTests/FilePathComponentsTest.swift @@ -15,7 +15,7 @@ import XCTest @testable import System #endif -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) struct TestPathComponents: TestCase { var path: FilePath var expectedRoot: FilePath.Root? @@ -100,7 +100,7 @@ struct TestPathComponents: TestCase { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class FilePathComponentsTest: XCTestCase { func testAdHocRRC() { var path: FilePath = "/usr/local/bin" diff --git a/Tests/SystemTests/FilePathTests/FilePathDecodable.swift b/Tests/SystemTests/FilePathTests/FilePathDecodable.swift index 290bef2f..b88b0299 100644 --- a/Tests/SystemTests/FilePathTests/FilePathDecodable.swift +++ b/Tests/SystemTests/FilePathTests/FilePathDecodable.swift @@ -15,7 +15,7 @@ import XCTest @testable import System #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class FilePathDecodableTest: XCTestCase { func testInvalidFilePath() { // _storage is a valid SystemString, but the invariants of FilePath are diff --git a/Tests/SystemTests/FilePathTests/FilePathExtras.swift b/Tests/SystemTests/FilePathTests/FilePathExtras.swift index 82f11373..ff4b1b37 100644 --- a/Tests/SystemTests/FilePathTests/FilePathExtras.swift +++ b/Tests/SystemTests/FilePathTests/FilePathExtras.swift @@ -6,7 +6,7 @@ #endif // Why can't I write this extension on `FilePath.ComponentView.SubSequence`? -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension Slice where Base == FilePath.ComponentView { internal var _storageSlice: SystemString.SubSequence { base._path._storage[self.startIndex._storage ..< self.endIndex._storage] @@ -15,7 +15,7 @@ extension Slice where Base == FilePath.ComponentView { // Proposed API that didn't make the cut, but we stil want to keep our testing for -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Returns `self` relative to `base`. /// This does not cosult the file system or resolve symlinks. diff --git a/Tests/SystemTests/FilePathTests/FilePathParsingTest.swift b/Tests/SystemTests/FilePathTests/FilePathParsingTest.swift index 766bdf8d..66e9105e 100644 --- a/Tests/SystemTests/FilePathTests/FilePathParsingTest.swift +++ b/Tests/SystemTests/FilePathTests/FilePathParsingTest.swift @@ -68,7 +68,7 @@ extension ParsingTestCase { @testable import System #endif -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class FilePathParsingTest: XCTestCase { func testNormalization() { let unixPaths: Array = [ diff --git a/Tests/SystemTests/FilePathTests/FilePathSyntaxTest.swift b/Tests/SystemTests/FilePathTests/FilePathSyntaxTest.swift index d23999a2..4e182556 100644 --- a/Tests/SystemTests/FilePathTests/FilePathSyntaxTest.swift +++ b/Tests/SystemTests/FilePathTests/FilePathSyntaxTest.swift @@ -146,7 +146,7 @@ extension SyntaxTestCase { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension SyntaxTestCase { func testComponents(_ path: FilePath, expected: [String]) { let expectedComponents = expected.map { FilePath.Component($0)! } @@ -342,7 +342,7 @@ private struct WindowsRootTestCase: TestCase { var line: UInt } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension WindowsRootTestCase { func runAllTests() { withWindowsPaths(enabled: true) { @@ -357,7 +357,7 @@ extension WindowsRootTestCase { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class FilePathSyntaxTest: XCTestCase { func testPathSyntax() { let unixPaths: Array = [ diff --git a/Tests/SystemTests/FilePathTests/FilePathTest.swift b/Tests/SystemTests/FilePathTests/FilePathTest.swift index b50cc17e..ef71c850 100644 --- a/Tests/SystemTests/FilePathTests/FilePathTest.swift +++ b/Tests/SystemTests/FilePathTests/FilePathTest.swift @@ -15,7 +15,7 @@ import SystemPackage import System #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) func filePathFromInvalidCodePointSequence(_ bytes: S) -> FilePath where S.Element == CInterop.PlatformUnicodeEncoding.CodeUnit { var array = Array(bytes) assert(array.last != 0, "already null terminated") @@ -28,7 +28,7 @@ func filePathFromInvalidCodePointSequence(_ bytes: S) -> FilePath w } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class FilePathTest: XCTestCase { struct TestPath { let filePath: FilePath diff --git a/Tests/SystemTests/FileTypesTest.swift b/Tests/SystemTests/FileTypesTest.swift index 5258709a..75d748b0 100644 --- a/Tests/SystemTests/FileTypesTest.swift +++ b/Tests/SystemTests/FileTypesTest.swift @@ -18,7 +18,7 @@ import System import Android #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class FileDescriptorTest: XCTestCase { func testStandardDescriptors() { XCTAssertEqual(FileDescriptor.standardInput.rawValue, 0) @@ -74,7 +74,7 @@ final class FileDescriptorTest: XCTestCase { } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class FilePermissionsTest: XCTestCase { func testPermissions() { diff --git a/Tests/SystemTests/MachPortTests.swift b/Tests/SystemTests/MachPortTests.swift index 073da9a5..fde04d8c 100644 --- a/Tests/SystemTests/MachPortTests.swift +++ b/Tests/SystemTests/MachPortTests.swift @@ -18,7 +18,7 @@ import SystemPackage import System #endif -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) final class MachPortTests: XCTestCase { func refCountForMachPortName(name:mach_port_name_t, kind:mach_port_right_t) -> mach_port_urefs_t { var refCount:mach_port_urefs_t = .max diff --git a/Tests/SystemTests/MockingTest.swift b/Tests/SystemTests/MockingTest.swift index 1f2c96da..38985c6b 100644 --- a/Tests/SystemTests/MockingTest.swift +++ b/Tests/SystemTests/MockingTest.swift @@ -15,7 +15,7 @@ import XCTest @testable import System #endif -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class MockingTest: XCTestCase { func testMocking() { XCTAssertFalse(mockingEnabled) diff --git a/Utilities/expand-availability.py b/Utilities/expand-availability.py deleted file mode 100755 index 4cb1a1be..00000000 --- a/Utilities/expand-availability.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 - -# This script can be used to automatically add/remove `@available` attributes to -# declarations in Swift sources in this package. -# -# In order for this to work, ABI-impacting declarations need to be annotated -# with special comments in the following format: -# -# @available(/*System 0.0.2*/iOS 8, *) -# public func greeting() -> String { -# "Hello" -# } -# -# (The iOS 8 availability is a dummy no-op declaration -- it only has to be -# there because `@available(*)` isn't valid syntax, and commenting out the -# entire `@available` attribute would interfere with parser tools for doc -# comments. `iOS 8` is the shortest version string that matches the minimum -# possible deployment target for Swift code, so we use that as our dummy -# availability version. `@available(iOS 8, *)` is functionally equivalent to not -# having an `@available` attribute at all.) -# -# The script adds full availability incantations to these comments. It can run -# in one of two modes: -# -# By default, `expand-availability.py` expands availability macros within the -# comments. This is useful during package development to cross-reference -# availability across `SystemPackage` and the ABI-stable `System` module that -# ships in Apple's OS releases: -# -# @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -# public func greeting() -> String { -# "Hello" -# } -# -# `expand-availability.py --attributes` adds actual availability declarations. -# This is used by maintainers to build ABI stable releases of System on Apple's -# platforms: -# -# @available(/*System 0.0.2: */macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) -# public func greeting() -> String { -# "Hello" -# } -# -# The script recognizes all three forms of these annotations and updates them on -# every run, so we can run the script to enable/disable attributes as needed. - -import os -import os.path -import fileinput -import re -import sys -import argparse - -versions = { - "System 0.0.1": "macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0", - "System 0.0.2": "macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0", - "System 1.1.0": "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4", - "System 1.2.0": "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999", - "System 1.3.0": "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999", - "System 1.4.0": "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999", -} - -parser = argparse.ArgumentParser(description="Expand availability macros.") -parser.add_argument("--attributes", help="Add @available attributes", - action="store_true") -args = parser.parse_args() - -def swift_sources_in(path): - result = [] - for (dir, _, files) in os.walk(path): - for file in files: - extension = os.path.splitext(file)[1] - if extension == ".swift": - result.append(os.path.join(dir, file)) - return result - -# Old-style syntax: -# /*System 0.0.2*/ -# /*System 0.0.2, @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)*/ -# /*System 0.0.2*/@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) -old_macro_pattern = re.compile( - r"/\*(System [^ *]+)(, @available\([^)]*\))?\*/(@available\([^)]*\))?") - -# New-style comments: -# @available(/*SwiftSystem 0.0.2*/macOS 10, *) -# @available(/*SwiftSystem 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -# @available(/*SwiftSystem 0.0.2*/macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) -# -# These do not interfere with our tools' ability to find doc comments. -macro_pattern = re.compile( - r"@available\(/\*(System [^ *:]+)[^*/)]*\*/([^)]*)\*\)") - -def available_attribute(filename, lineno, symbolic_version): - expansion = versions[symbolic_version] - if expansion is None: - raise ValueError("{0}:{1}: error: Unknown System version '{0}'" - .format(fileinput.filename(), fileinput.lineno(), symbolic_version)) - if args.attributes: - attribute = "@available(/*{0}*/{1}, *)".format(symbolic_version, expansion) - else: - # Sadly `@available(*)` is not valid syntax, so we have to mention at - # least one actual platform here. - attribute = "@available(/*{0}: {1}*/iOS 8, *)".format(symbolic_version, expansion) - return attribute - - -sources = swift_sources_in("Sources") + swift_sources_in("Tests") -for line in fileinput.input(files=sources, inplace=True): - match = re.search(macro_pattern, line) - if match is None: - match = re.search(old_macro_pattern, line) - if match: - symbolic_version = match.group(1) - replacement = available_attribute( - fileinput.filename(), fileinput.lineno(), symbolic_version) - line = line[:match.start()] + replacement + line[match.end():] - print(line, end="")