diff --git a/WireAPI/Package.swift b/WireAPI/Package.swift
index ca9ddf14b32..0a655151855 100644
--- a/WireAPI/Package.swift
+++ b/WireAPI/Package.swift
@@ -27,7 +27,8 @@ let package = Package(
url: "https://github.com/pointfreeco/swift-snapshot-testing",
from: "1.16.0"
),
- .package(path: "../SourceryPlugin")
+ .package(path: "../SourceryPlugin"),
+ .package(path: "../WireMacros")
],
targets: [
.target(
@@ -47,6 +48,7 @@ let package = Package(
name: "WireAPITests",
dependencies: [
"WireAPI",
+ "WireMacros",
.product(
name: "SnapshotTesting",
package: "swift-snapshot-testing"
diff --git a/WireAPI/Tests/WireAPITests/APIs/ConversationsAPI/ConversationsAPITests.swift b/WireAPI/Tests/WireAPITests/APIs/ConversationsAPI/ConversationsAPITests.swift
index 33a202a482d..93cd7e86a5b 100644
--- a/WireAPI/Tests/WireAPITests/APIs/ConversationsAPI/ConversationsAPITests.swift
+++ b/WireAPI/Tests/WireAPITests/APIs/ConversationsAPI/ConversationsAPITests.swift
@@ -16,6 +16,7 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//
+import WireMacros
import XCTest
@testable import WireAPI
@@ -107,7 +108,7 @@ final class ConversationsAPITests: XCTestCase {
]
let expectedIDs: [UUID] = [
- try XCTUnwrap(UUID(uuidString: "14c3f0ff-1a46-4e66-8845-ae084f09c483"))
+ #UUID("14c3f0ff-1a46-4e66-8845-ae084f09c483")
]
let api = ConversationsAPIV0(httpClient: httpClient)
@@ -175,7 +176,7 @@ final class ConversationsAPITests: XCTestCase {
let expectedIDs: [QualifiedID] = [
QualifiedID(
- uuid: try XCTUnwrap(UUID(uuidString: "14c3f0ff-1a46-4e66-8845-ae084f09c483")),
+ uuid: #UUID("14c3f0ff-1a46-4e66-8845-ae084f09c483"),
domain: "staging.zinfra.io"
)
]
@@ -220,7 +221,7 @@ final class ConversationsAPITests: XCTestCase {
let apiVersions = APIVersion.allCases
let qualifiedID = QualifiedID(
- uuid: try XCTUnwrap(UUID(uuidString: "213248a1-5499-418f-8173-5010d1c1e506")),
+ uuid: #UUID("213248a1-5499-418f-8173-5010d1c1e506"),
domain: "wire.com"
)
diff --git a/WireMacros/.gitignore b/WireMacros/.gitignore
new file mode 100644
index 00000000000..0023a534063
--- /dev/null
+++ b/WireMacros/.gitignore
@@ -0,0 +1,8 @@
+.DS_Store
+/.build
+/Packages
+xcuserdata/
+DerivedData/
+.swiftpm/configuration/registries.json
+.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
+.netrc
diff --git a/WireMacros/.swiftpm/xcode/xcshareddata/xcschemes/WireMacros.xcscheme b/WireMacros/.swiftpm/xcode/xcshareddata/xcschemes/WireMacros.xcscheme
new file mode 100644
index 00000000000..c5a0735659e
--- /dev/null
+++ b/WireMacros/.swiftpm/xcode/xcshareddata/xcschemes/WireMacros.xcscheme
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WireMacros/.swiftpm/xcode/xcshareddata/xcschemes/WireMacrosClient.xcscheme b/WireMacros/.swiftpm/xcode/xcshareddata/xcschemes/WireMacrosClient.xcscheme
new file mode 100644
index 00000000000..9a632c61b8e
--- /dev/null
+++ b/WireMacros/.swiftpm/xcode/xcshareddata/xcschemes/WireMacrosClient.xcscheme
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WireMacros/Package.swift b/WireMacros/Package.swift
new file mode 100644
index 00000000000..2b92baff51d
--- /dev/null
+++ b/WireMacros/Package.swift
@@ -0,0 +1,51 @@
+// swift-tools-version: 5.10
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+import CompilerPluginSupport
+
+let package = Package(
+ name: "WireMacros",
+ platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
+ products: [
+ // Products define the executables and libraries a package produces, making them visible to other packages.
+ .library(
+ name: "WireMacros",
+ targets: ["WireMacros"]
+ ),
+ .executable(
+ name: "WireMacrosClient",
+ targets: ["WireMacrosClient"]
+ ),
+ ],
+ dependencies: [
+ .package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0"),
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package, defining a module or a test suite.
+ // Targets can depend on other targets in this package and products from dependencies.
+ // Macro implementation that performs the source transformation of a macro.
+ .macro(
+ name: "WireMacrosMacros",
+ dependencies: [
+ .product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
+ .product(name: "SwiftCompilerPlugin", package: "swift-syntax")
+ ]
+ ),
+
+ // Library that exposes a macro as part of its API, which is used in client programs.
+ .target(name: "WireMacros", dependencies: ["WireMacrosMacros"]),
+
+ // A client of the library, which is able to use the macro in its own code.
+ .executableTarget(name: "WireMacrosClient", dependencies: ["WireMacros"]),
+
+ // A test target used to develop the macro implementation.
+ .testTarget(
+ name: "WireMacrosTests",
+ dependencies: [
+ "WireMacrosMacros",
+ .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
+ ]
+ ),
+ ]
+)
diff --git a/WireMacros/Sources/WireMacros/WireMacros.swift b/WireMacros/Sources/WireMacros/WireMacros.swift
new file mode 100644
index 00000000000..3cbf9c4e63a
--- /dev/null
+++ b/WireMacros/Sources/WireMacros/WireMacros.swift
@@ -0,0 +1,88 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+import Foundation
+
+/// A macro that, when attached to a protocol declaration, produces a
+/// companion "provider" protocol that can be used inject dependencies.
+///
+/// For example:
+///
+/// @Provided
+/// protocol MyUseCase {
+/// func invoke()
+/// }
+///
+/// will expand to:
+///
+/// protocol MyUseCase {
+/// func invoke()
+/// }
+///
+/// protocol MyUseCaseProvider {
+/// func makeMyUseCase() -> any MyUseCase
+/// }
+///
+/// Any object that is capable of providing the use case can
+/// conform to the provider protocol:
+///
+/// extension Factory: MyUseCaseProvider {
+/// func makeMyUseCase() -> any MyUseCase {
+/// MyUseCase(...)
+/// }
+/// }
+///
+/// Instead of injecting a concrete `Factory`, we can now inject
+/// some provider:
+///
+/// class MyViewModel {
+///
+/// let provider: some MyUseCaseProvider
+///
+/// func doSomething() {
+/// let useCase = provider.makeMyUseCase()
+/// useCase.invoke()
+/// }
+///
+/// }
+
+@attached(peer, names: suffixed(Provider))
+public macro Provided() = #externalMacro(
+ module: "WireMacrosMacros",
+ type: "ProvidedMacro"
+)
+
+/// A macro that validates UUID strings.
+///
+/// For example:
+///
+/// let validUUID = #UUID("7411ca17-ba08-4905-92d2-0617a8c810ca")
+///
+/// will compile and produce a non-optional `UUID`. On the otherhand:
+///
+/// let invalidUUID = #UUID("foo")
+///
+/// will throw a compile time error.
+
+@freestanding(expression)
+public macro UUID(
+ _ stringLiteral: String
+) -> UUID = #externalMacro(
+ module: "WireMacrosMacros",
+ type: "UUIDMacro"
+)
diff --git a/WireMacros/Sources/WireMacrosClient/main.swift b/WireMacros/Sources/WireMacrosClient/main.swift
new file mode 100644
index 00000000000..ac0f6bda611
--- /dev/null
+++ b/WireMacros/Sources/WireMacrosClient/main.swift
@@ -0,0 +1,46 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+import Foundation
+import WireMacros
+
+@Provided
+public protocol FooUseCaseProtocol {
+
+ func invoke()
+
+}
+
+struct FooUseCase: FooUseCaseProtocol {
+
+ func invoke() {
+
+ }
+
+}
+
+struct FooUseCaseProvider: FooUseCaseProtocolProvider {
+
+ func makeFooUseCaseProtocol() -> any FooUseCaseProtocol {
+ FooUseCase()
+ }
+
+}
+
+let uuid = #UUID("7411ca17-ba08-4905-92d2-0617a8c810ca")
+print(uuid)
diff --git a/WireMacros/Sources/WireMacrosMacros/Provided/ProvidedMacro.swift b/WireMacros/Sources/WireMacrosMacros/Provided/ProvidedMacro.swift
new file mode 100644
index 00000000000..d27c780de20
--- /dev/null
+++ b/WireMacros/Sources/WireMacrosMacros/Provided/ProvidedMacro.swift
@@ -0,0 +1,59 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+import SwiftSyntax
+import SwiftSyntaxBuilder
+import SwiftSyntaxMacros
+
+public struct ProvidedMacro: PeerMacro {
+
+ public static func expansion(
+ of node: AttributeSyntax,
+ providingPeersOf declaration: some DeclSyntaxProtocol,
+ in context: some MacroExpansionContext
+ ) throws -> [DeclSyntax] {
+ guard let protocolDeclaration = declaration.as(ProtocolDeclSyntax.self) else {
+ throw ProvidedMacroError.notAttachedToProtocol
+ }
+
+ let isPrivate = protocolDeclaration.modifiers.contains {
+ $0.name.tokenKind == .keyword(.private)
+ }
+
+ guard !isPrivate else {
+ throw ProvidedMacroError.privateProtocol
+ }
+
+ let isPublic = protocolDeclaration.modifiers.contains {
+ $0.name.tokenKind == .keyword(.public)
+ }
+
+ let name = protocolDeclaration.name.text
+
+ let output = """
+ \(isPublic ? "public " : "")protocol \(name)Provider {
+
+ func make\(name)() -> any \(name)
+
+ }
+ """
+
+ return [DeclSyntax(stringLiteral: output)]
+ }
+
+}
diff --git a/WireMacros/Sources/WireMacrosMacros/Provided/ProvidedMacroError.swift b/WireMacros/Sources/WireMacrosMacros/Provided/ProvidedMacroError.swift
new file mode 100644
index 00000000000..b27d2388bf3
--- /dev/null
+++ b/WireMacros/Sources/WireMacrosMacros/Provided/ProvidedMacroError.swift
@@ -0,0 +1,34 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+public enum ProvidedMacroError: Error, CustomStringConvertible {
+
+ case notAttachedToProtocol
+ case privateProtocol
+
+ public var description: String {
+ switch self {
+ case .notAttachedToProtocol:
+ "@Provided can only be attached to a protocol"
+
+ case .privateProtocol:
+ "@Provided can not be attached to a private protocol"
+ }
+ }
+
+}
diff --git a/WireMacros/Sources/WireMacrosMacros/UUID/UUIDMacro.swift b/WireMacros/Sources/WireMacrosMacros/UUID/UUIDMacro.swift
new file mode 100644
index 00000000000..c83915c5652
--- /dev/null
+++ b/WireMacros/Sources/WireMacrosMacros/UUID/UUIDMacro.swift
@@ -0,0 +1,48 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+import Foundation
+import SwiftSyntax
+import SwiftSyntaxBuilder
+import SwiftSyntaxMacros
+
+public struct UUIDMacro: ExpressionMacro {
+
+ public static func expansion(
+ of node: some FreestandingMacroExpansionSyntax,
+ in context: some MacroExpansionContext
+ ) throws -> ExprSyntax {
+ // Ensure a single string literal argument.
+ guard
+ let argument = node.argumentList.first?.expression,
+ let segments = argument.as(StringLiteralExprSyntax.self)?.segments,
+ segments.count == 1,
+ case .stringSegment(let literalSegment)? = segments.first
+ else {
+ throw UUIDMacroError.requiresStringLiteralArgument
+ }
+
+ // Validate.
+ guard let _ = UUID(uuidString: literalSegment.content.text) else {
+ throw UUIDMacroError.invalidUUID("\(argument)")
+ }
+
+ return "UUID(uuidString: \(argument))!"
+ }
+
+}
diff --git a/WireMacros/Sources/WireMacrosMacros/UUID/UUIDMacroError.swift b/WireMacros/Sources/WireMacrosMacros/UUID/UUIDMacroError.swift
new file mode 100644
index 00000000000..66507da595f
--- /dev/null
+++ b/WireMacros/Sources/WireMacrosMacros/UUID/UUIDMacroError.swift
@@ -0,0 +1,34 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+public enum UUIDMacroError: Error, CustomStringConvertible {
+
+ case requiresStringLiteralArgument
+ case invalidUUID(String)
+
+ public var description: String {
+ switch self {
+ case .requiresStringLiteralArgument:
+ "#UUID requires a string literal argument."
+ case .invalidUUID(let string):
+ "\(string) is not a valid UUID."
+ }
+ }
+
+}
+
diff --git a/WireMacros/Sources/WireMacrosMacros/WireMacrosMacro.swift b/WireMacros/Sources/WireMacrosMacros/WireMacrosMacro.swift
new file mode 100644
index 00000000000..638a3d0bb31
--- /dev/null
+++ b/WireMacros/Sources/WireMacrosMacros/WireMacrosMacro.swift
@@ -0,0 +1,28 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+import SwiftCompilerPlugin
+import SwiftSyntaxMacros
+
+@main
+struct WireMacrosPlugin: CompilerPlugin {
+ let providingMacros: [Macro.Type] = [
+ ProvidedMacro.self,
+ UUIDMacro.self
+ ]
+}
diff --git a/WireMacros/Tests/WireMacrosTests/ProvidedMacroTests.swift b/WireMacros/Tests/WireMacrosTests/ProvidedMacroTests.swift
new file mode 100644
index 00000000000..90c127832d0
--- /dev/null
+++ b/WireMacros/Tests/WireMacrosTests/ProvidedMacroTests.swift
@@ -0,0 +1,149 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+import SwiftSyntax
+import SwiftSyntaxBuilder
+import SwiftSyntaxMacros
+import SwiftSyntaxMacrosTestSupport
+import XCTest
+
+// Macro implementations build for the host, so the corresponding module is not available
+// when cross-compiling. Cross-compiled tests may still make use of the macro itself in
+// end-to-end tests.
+#if canImport(WireMacrosMacros)
+import WireMacrosMacros
+
+private let testMacros: [String: Macro.Type] = [
+ "Provided": ProvidedMacro.self
+]
+#endif
+
+final class ProvidedMacrosTests: XCTestCase {
+
+ func testItCreatesPublicProviderProtocol() throws {
+ #if canImport(WireMacrosMacros)
+ assertMacroExpansion(
+ """
+ @Provided
+ public protocol MyUseCaseProtocol {
+ func invoke()
+ }
+ """,
+ expandedSource: """
+ public protocol MyUseCaseProtocol {
+ func invoke()
+ }
+
+ public protocol MyUseCaseProtocolProvider {
+
+ func makeMyUseCaseProtocol() -> any MyUseCaseProtocol
+
+ }
+ """,
+ macros: testMacros
+ )
+ #else
+ throw XCTSkip("macros are only supported when running tests for the host platform")
+ #endif
+ }
+
+ func testItCreatesInternalProviderProtocol() throws {
+ #if canImport(WireMacrosMacros)
+ assertMacroExpansion(
+ """
+ @Provided
+ protocol MyUseCaseProtocol {
+ func invoke()
+ }
+ """,
+ expandedSource: """
+ protocol MyUseCaseProtocol {
+ func invoke()
+ }
+
+ protocol MyUseCaseProtocolProvider {
+
+ func makeMyUseCaseProtocol() -> any MyUseCaseProtocol
+
+ }
+ """,
+ macros: testMacros
+ )
+ #else
+ throw XCTSkip("macros are only supported when running tests for the host platform")
+ #endif
+ }
+
+ func testItDoesNotCreatePrivateProviderProtocol() throws {
+ #if canImport(WireMacrosMacros)
+ assertMacroExpansion(
+ """
+ @Provided
+ private protocol MyUseCaseProtocol {
+ func invoke()
+ }
+ """,
+ expandedSource: """
+ private protocol MyUseCaseProtocol {
+ func invoke()
+ }
+ """,
+ diagnostics: [
+ DiagnosticSpec(
+ message: "@Provided can not be attached to a private protocol",
+ line: 1,
+ column: 1
+ )
+ ],
+ macros: testMacros
+ )
+ #else
+ throw XCTSkip("macros are only supported when running tests for the host platform")
+ #endif
+ }
+
+ func testItThrowsErrorIfNotAttachedToProtocol() throws {
+ #if canImport(WireMacrosMacros)
+ assertMacroExpansion(
+ """
+ @Provided
+ enum MyEnum {
+ case foo
+ }
+ """,
+ expandedSource: """
+ enum MyEnum {
+ case foo
+ }
+ """,
+ diagnostics: [
+ DiagnosticSpec(
+ message: "@Provided can only be attached to a protocol",
+ line: 1,
+ column: 1
+ )
+ ],
+ macros: testMacros
+ )
+ #else
+ throw XCTSkip("macros are only supported when running tests for the host platform")
+ #endif
+ }
+
+}
+
diff --git a/WireMacros/Tests/WireMacrosTests/UUIDMacroTests.swift b/WireMacros/Tests/WireMacrosTests/UUIDMacroTests.swift
new file mode 100644
index 00000000000..f1494a0c115
--- /dev/null
+++ b/WireMacros/Tests/WireMacrosTests/UUIDMacroTests.swift
@@ -0,0 +1,101 @@
+//
+// Wire
+// Copyright (C) 2024 Wire Swiss GmbH
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see http://www.gnu.org/licenses/.
+//
+
+import SwiftSyntax
+import SwiftSyntaxBuilder
+import SwiftSyntaxMacros
+import SwiftSyntaxMacrosTestSupport
+import XCTest
+
+// Macro implementations build for the host, so the corresponding module is not available
+// when cross-compiling. Cross-compiled tests may still make use of the macro itself in
+// end-to-end tests.
+
+#if canImport(WireMacrosMacros)
+import WireMacrosMacros
+
+private let testMacros: [String: Macro.Type] = [
+ "UUID": UUIDMacro.self
+]
+#endif
+
+final class UUIDMacrosTests: XCTestCase {
+
+ func testItExpandsAValidUUID() throws {
+ #if canImport(WireMacrosMacros)
+ assertMacroExpansion("""
+ let uuid = #UUID("7411ca17-ba08-4905-92d2-0617a8c810ca")
+ """,
+ expandedSource: """
+ let uuid = UUID(uuidString: "7411ca17-ba08-4905-92d2-0617a8c810ca")!
+ """,
+ macros: testMacros
+ )
+ #else
+ throw XCTSkip("macros are only supported when running tests for the host platform")
+ #endif
+ }
+
+ func testItThrowsErrorWithInvalidUUID() throws {
+ #if canImport(WireMacrosMacros)
+ assertMacroExpansion("""
+ let uuid = #UUID("foo")
+ """,
+ expandedSource: """
+ let uuid = #UUID("foo")
+ """,
+ diagnostics: [
+ DiagnosticSpec(
+ message: "\"foo\" is not a valid UUID.",
+ line: 1,
+ column: 12
+ )
+ ],
+ macros: testMacros
+ )
+ #else
+ throw XCTSkip("macros are only supported when running tests for the host platform")
+ #endif
+ }
+
+ func testItThrowsErrorIfNotPassedAStringLiteral() throws {
+ #if canImport(WireMacrosMacros)
+ assertMacroExpansion("""
+ let string = "7411ca17-ba08-4905-92d2-0617a8c810ca"
+ let uuid = #UUID(string)
+ """,
+ expandedSource: """
+ let string = "7411ca17-ba08-4905-92d2-0617a8c810ca"
+ let uuid = #UUID(string)
+ """,
+ diagnostics: [
+ DiagnosticSpec(
+ message: "#UUID requires a string literal argument.",
+ line: 2,
+ column: 12
+ )
+ ],
+ macros: testMacros
+ )
+ #else
+ throw XCTSkip("macros are only supported when running tests for the host platform")
+ #endif
+ }
+
+}
+
diff --git a/WireMacros/Tests/WireMacrosTests/WireMacros.xctestplan b/WireMacros/Tests/WireMacrosTests/WireMacros.xctestplan
new file mode 100644
index 00000000000..865aa8413ba
--- /dev/null
+++ b/WireMacros/Tests/WireMacrosTests/WireMacros.xctestplan
@@ -0,0 +1,24 @@
+{
+ "configurations" : [
+ {
+ "id" : "A6812806-2731-4498-8D38-338B8651511D",
+ "name" : "Test Scheme Action",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "codeCoverage" : false
+ },
+ "testTargets" : [
+ {
+ "target" : {
+ "containerPath" : "container:",
+ "identifier" : "WireMacrosTests",
+ "name" : "WireMacrosTests"
+ }
+ }
+ ],
+ "version" : 1
+}
diff --git a/wire-ios-mono.xcworkspace/contents.xcworkspacedata b/wire-ios-mono.xcworkspace/contents.xcworkspacedata
index 0ae82d115e3..45f7c94b188 100644
--- a/wire-ios-mono.xcworkspace/contents.xcworkspacedata
+++ b/wire-ios-mono.xcworkspace/contents.xcworkspacedata
@@ -121,7 +121,13 @@
+
+
+
+
diff --git a/wire-ios-mono.xcworkspace/xcshareddata/swiftpm/Package.resolved b/wire-ios-mono.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 04775339201..ec690cc1c1f 100644
--- a/wire-ios-mono.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/wire-ios-mono.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -64,6 +64,24 @@
"version": "0.5.2"
}
},
+ {
+ "package": "PINCache",
+ "repositoryURL": "https://github.com/pinterest/PINCache",
+ "state": {
+ "branch": null,
+ "revision": "2fb85948463292c2e824148cf17dc62a4c217a94",
+ "version": "3.0.4"
+ }
+ },
+ {
+ "package": "PINOperation",
+ "repositoryURL": "https://github.com/pinterest/PINOperation.git",
+ "state": {
+ "branch": null,
+ "revision": "a74f978733bdaf982758bfa23d70a189f4b4c1b6",
+ "version": "1.2.3"
+ }
+ },
{
"package": "PLCrashReporter",
"repositoryURL": "https://github.com/microsoft/plcrashreporter.git",
@@ -138,7 +156,7 @@
},
{
"package": "swift-log",
- "repositoryURL": "https://github.com/apple/swift-log.git",
+ "repositoryURL": "https://github.com/apple/swift-log",
"state": {
"branch": null,
"revision": "e97a6fcb1ab07462881ac165fdbb37f067e205d5",
@@ -222,8 +240,8 @@
"repositoryURL": "https://github.com/apple/swift-syntax",
"state": {
"branch": null,
- "revision": "303e5c5c36d6a558407d364878df131c3546fad8",
- "version": "510.0.2"
+ "revision": "64889f0c732f210a935a0ad7cda38f77f876262d",
+ "version": "509.1.1"
}
},
{