diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 188204d6..bd4f2101 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -50,6 +50,25 @@ jobs: - name: Build run: cmake --build .cmake-build + wasm-build: + name: Wasm Build + runs-on: ubuntu-latest + container: + image: swift:6.1-noble + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Install Swift SDKs for WebAssembly + run: | + # TODO: We can replace these Swift SDKs with the swift.org one once it supports Foundation. + swift sdk install https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.1-RELEASE/swift-wasm-6.1-RELEASE-wasm32-unknown-wasi.artifactbundle.zip --checksum 7550b4c77a55f4b637c376f5d192f297fe185607003a6212ad608276928db992 + swift sdk install https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.1-RELEASE/swift-wasm-6.1-RELEASE-wasm32-unknown-wasip1-threads.artifactbundle.zip --checksum 0dd273be28741f8e1eb00682c39bdc956361ed24b5572e183dd8a4e9d1c5f6ec + swift sdk list + - name: Build + run: | + swift build --swift-sdk wasm32-unknown-wasi --target ArgumentParser + swift build --swift-sdk wasm32-unknown-wasip1-threads --target ArgumentParser + soundness: name: Soundness uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main diff --git a/Sources/ArgumentParser/Parsable Properties/CompletionKind.swift b/Sources/ArgumentParser/Parsable Properties/CompletionKind.swift index 82739618..97573656 100644 --- a/Sources/ArgumentParser/Parsable Properties/CompletionKind.swift +++ b/Sources/ArgumentParser/Parsable Properties/CompletionKind.swift @@ -41,6 +41,9 @@ public struct CompletionKind { case directory case shellCommand(String) case custom(@Sendable ([String], Int, String) -> [String]) + #if !canImport(Dispatch) + @available(*, unavailable, message: "DispatchSemaphore is unavailable") + #endif case customAsync(@Sendable ([String], Int, String) async -> [String]) case customDeprecated(@Sendable ([String]) -> [String]) } @@ -181,11 +184,18 @@ public struct CompletionKind { /// /// The same as `custom(@Sendable @escaping ([String], Int, String) -> [String])`, /// except that the closure is asynchronous. + #if !canImport(Dispatch) + @available(*, unavailable, message: "DispatchSemaphore is unavailable") + #endif @available(macOS 10.15, macCatalyst 13, iOS 13, tvOS 13, watchOS 6, *) public static func custom( _ completion: @Sendable @escaping ([String], Int, String) async -> [String] ) -> CompletionKind { + #if !canImport(Dispatch) + fatalError("DispatchSemaphore is unavailable") + #else CompletionKind(kind: .customAsync(completion)) + #endif } /// Deprecated; only kept for backwards compatibility. diff --git a/Sources/ArgumentParser/Parsing/CommandParser.swift b/Sources/ArgumentParser/Parsing/CommandParser.swift index b8d9b972..3f2f08cc 100644 --- a/Sources/ArgumentParser/Parsing/CommandParser.swift +++ b/Sources/ArgumentParser/Parsing/CommandParser.swift @@ -10,11 +10,15 @@ //===----------------------------------------------------------------------===// #if swift(>=6.0) +#if canImport(Dispatch) @preconcurrency private import class Dispatch.DispatchSemaphore +#endif internal import class Foundation.NSLock internal import class Foundation.ProcessInfo #else +#if canImport(Dispatch) @preconcurrency import class Dispatch.DispatchSemaphore +#endif import class Foundation.NSLock import class Foundation.ProcessInfo #endif @@ -474,12 +478,16 @@ extension CommandParser { completingPrefix ) case .customAsync(let complete): + #if canImport(Dispatch) if #available(macOS 10.15, macCatalyst 13, iOS 13, tvOS 13, watchOS 6, *) { completions = try asyncCustomCompletions(from: args, complete: complete) } else { throw ParserError.invalidState } + #else + throw ParserError.invalidState + #endif case .customDeprecated(let complete): completions = complete(args) default: @@ -528,11 +536,17 @@ private func parseCustomCompletionArguments( return (Array(args), completingArgumentIndex, completingPrefix) } +#if !canImport(Dispatch) +@available(*, unavailable, message: "DispatchSemaphore is unavailable") +#endif @available(macOS 10.15, macCatalyst 13, iOS 13, tvOS 13, watchOS 6, *) private func asyncCustomCompletions( from args: [String], complete: @escaping @Sendable ([String], Int, String) async -> [String] ) throws -> [String] { + #if !canImport(Dispatch) + throw ParserError.invalidState + #else let (args, completingArgumentIndex, completingPrefix) = try parseCustomCompletionArguments(from: args) @@ -550,6 +564,7 @@ private func asyncCustomCompletions( semaphore.wait() return completionsBox.value + #endif } // Helper class to make values sendable across concurrency boundaries