Skip to content

Commit

Permalink
Protocol stub and instance adjustment (#11)
Browse files Browse the repository at this point in the history
* Fix member macro not working

* Make stub instance as computed property

* Remove given name argument that violate Swift Macros spec

* Update unit test

* update README

* Refactor to satisfy linter
  • Loading branch information
hainayanda authored Apr 20, 2024
1 parent 8ef24f2 commit 6d3c566
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 61 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ This library is designed to allow easier dependency management, using exisiting

```swift
// protocol with stub
@Stubbed
@Stubbed(type: .class)
protocol MyProtocol {
func doSomething()
}
Expand Down Expand Up @@ -139,7 +139,7 @@ The `Stubbed` macro simplifies the creation of stubs from protocols, reducing bo
```swift
import SwiftEnvironment

@Stubbed
@Stubbed(type: .struct)
protocol MyProtocol {
var someValue: Int { get }
func calculate(someValue: Int) -> Int
Expand All @@ -161,7 +161,7 @@ If the return type of the protocol's methods or variables is unknown or you want
```swift
import SwiftEnvironment

@Stubbed(.value(for: MyType.self, MyType()))
@Stubbed(type: .class, .value(for: MyType.self, MyType()))
protocol MyProtocol {
var someValue: MyType { get }
func calculate(someValue: Int) -> MyType
Expand Down
9 changes: 7 additions & 2 deletions Sources/SwiftEnvironment/Macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@ public macro EnvironmentValue() = #externalMacro(
module: "SwiftEnvironmentMacro", type: "EnvironmentValueMacro"
)

@attached(member, names: arbitrary)
public macro Stubbed() = #externalMacro(
module: "SwiftEnvironmentMacro", type: "StubGeneratorMacro"
)

@attached(peer, names: suffixed(Stub))
public macro Stubbed(name: String? = nil, type: StubType = .struct) = #externalMacro(
public macro Stubbed(type: StubType) = #externalMacro(
module: "SwiftEnvironmentMacro", type: "StubGeneratorMacro"
)

@attached(peer, names: suffixed(Stub))
public macro Stubbed(name: String? = nil, type: StubType = .struct, _ values: DefaultType...) = #externalMacro(
public macro Stubbed(type: StubType, _ values: DefaultType...) = #externalMacro(
module: "SwiftEnvironmentMacro", type: "StubGeneratorMacro"
)

Expand Down
6 changes: 3 additions & 3 deletions Sources/SwiftEnvironmentMacro/Model/StubInitializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ struct StubInitializer: CustomStringConvertible {
let argumentPairs: [InitArgumentPairs]

var description: String {
let singletonClause = "static var stub: \(name) = \(name)("
let singletonClause = "static var stub: \(name) { \(name)("
let arguments = argumentPairs.compactMap { $0.asArguments }.joined(separator: ", ")
if generateInit {
let initArguments = argumentPairs.compactMap { $0.asInitDeclaration }.joined(separator: ", ")
let body = argumentPairs.compactMap { $0.asInitBodyInitializer }.joined(separator: "\n ")
return """
\(singletonClause)\(arguments))
\(singletonClause)\(arguments)) }
init(\(initArguments)) {
\(body)
}
"""
}
return " \(singletonClause)\(arguments))"
return " \(singletonClause)\(arguments)) }"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ extension StubGeneratorMacro: PeerMacro {
for: protocolSyntax.name.text,
isObjectProtocol: isObjectProtocol
),
givenName: node.nameArgument,
with: DefaultValueGenerator(defaultValues: defaultValues)
)
return [ "\(raw: result.description)" ]
Expand All @@ -36,13 +35,6 @@ extension StubGeneratorMacro: PeerMacro {
// MARK: Private extensions

private extension AttributeSyntax {
var nameArgument: String? {
let argument = arguments?.as(LabeledExprListSyntax.self)?
.first { $0.label?.trimmedDescription == "name" }
guard let argument else { return nil }
return argument.expression.as(StringLiteralExprSyntax.self)?
.segments.first?.trimmedDescription
}

func typeArgument(for protocolName: String, isObjectProtocol: Bool) throws -> StubDeclaration.InstanceType {
let baseArgument = arguments?.as(LabeledExprListSyntax.self)?
Expand Down Expand Up @@ -132,9 +124,9 @@ private extension FunctionDeclSyntax {
}

private extension ProtocolDeclSyntax {
func defaultInstance(_ instanceType: StubDeclaration.InstanceType, givenName: String?, with defaultValues: DefaultValueGenerator) throws -> StubDeclaration {
func defaultInstance(_ instanceType: StubDeclaration.InstanceType, with defaultValues: DefaultValueGenerator) throws -> StubDeclaration {
try StubDeclaration(
instanceType: instanceType, name: "\(givenName ?? name.text)Stub",
instanceType: instanceType, name: "\(name.text)Stub",
variables: variables(with: defaultValues),
methods: methods(with: defaultValues)
)
Expand Down
12 changes: 11 additions & 1 deletion Tests/SwiftEnvironmentTests/DummyDependency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@
import Foundation
import SwiftEnvironment

@Stubbed
@Stubbed(type: .class)
protocol DummyDependency: AnyObject {
var id: UUID { get }
}

@Stubbed
struct DummyStruct {
let id: UUID
}

@Stubbed
struct DummyClass {
let id: UUID
}
5 changes: 5 additions & 0 deletions Tests/SwiftEnvironmentTests/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ final class IntegrationTests: XCTestCase {
XCTAssertEqual(dummy, "dummy")
}

func test_givenClassAndStruct_whenStubbed_shouldHaveStub() {
_ = DummyClass.stub
_ = DummyStruct.stub
}

}

typealias DummyEnvironmentKey = EnvironmentValues.DummySwiftEnvironmentKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,6 @@ final class StubFromProtocolGeneratorMacroTests: XCTestCase {
)
}

func test_givenNamedProtocol_shouldGenerateDefault() {
assertMacroExpansion(
namedProtocol,
expandedSource: namedProtocolExpansion,
macros: ["Stubbed": StubGeneratorMacro.self]
)
}

func test_givenClassProtocol_shouldGenerateDefault() {
assertMacroExpansion(
classProtocol,
Expand Down Expand Up @@ -102,7 +94,7 @@ final class StubFromProtocolGeneratorMacroTests: XCTestCase {
}

private let anyObjectProtocol: String = """
@Stubbed
@Stubbed(type: .class)
protocol Some: AnyObject {
var int: Int { get }
}
Expand All @@ -121,7 +113,7 @@ final class SomeStub: Some {
"""

private let allArgsProtocol: String = """
@Stubbed(name: "SomeName", type: .subclass(Super.self), .value(for: Int.self, 1), .value(for: Unknown.self, Unknown()))
@Stubbed(type: .subclass(Super.self), .value(for: Int.self, 1), .value(for: Unknown.self, Unknown()))
protocol Some {
var int: Int { get }
var unknown: Unknown { get }
Expand All @@ -134,7 +126,7 @@ protocol Some {
var unknown: Unknown { get }
}
final class SomeNameStub: Super, Some {
final class SomeStub: Super, Some {
let int: Int = 1
let unknown: Unknown = Unknown()
init() {
Expand Down Expand Up @@ -162,7 +154,7 @@ struct SomeStub: Some {
"""

private let injectValueProtocol: String = """
@Stubbed(.value(for: Int.self, 1), .value(for: Unknown.self, Unknown()))
@Stubbed(type: .struct, .value(for: Int.self, 1), .value(for: Unknown.self, Unknown()))
protocol Some {
var int: Int { get }
var unknown: Unknown { get }
Expand Down Expand Up @@ -221,27 +213,8 @@ final class SomeStub: Some {
}
"""

private let namedProtocol: String = """
@Stubbed(name: "SomeName")
protocol Some {
var int: Int { get }
}
"""

private let namedProtocolExpansion: String = """
protocol Some {
var int: Int { get }
}
struct SomeNameStub: Some {
let int: Int = 0
init() {
}
}
"""

private let simpleProtocol: String = """
@Stubbed
@Stubbed(type: .struct)
protocol Some {
var int: Int { get }
var double: Double { get set }
Expand Down Expand Up @@ -303,7 +276,7 @@ struct SomeStub: Some {
"""

private let optionalProtocol: String = """
@Stubbed
@Stubbed(type: .struct)
protocol Some {
var int: Int? { get }
var double: Optional<Double> { get set }
Expand Down Expand Up @@ -356,7 +329,7 @@ struct SomeStub: Some {
"""

private let arrayProtocol: String = """
@Stubbed
@Stubbed(type: .struct)
protocol Some {
var int: [Int] { get }
var double: Array<Double> { get set }
Expand Down Expand Up @@ -409,7 +382,7 @@ struct SomeStub: Some {
"""

private let dictionaryProtocol: String = """
@Stubbed
@Stubbed(type: .struct)
protocol Some {
var int: [Int: Unknown] { get }
var double: Dictionary<Double, Unknown?> { get set }
Expand Down
24 changes: 17 additions & 7 deletions Tests/SwiftEnvironmentTests/StubFromTypeGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class Some {
init(double: Double) {
self.double = double
self.int = int
self.int = 0
}
}
"""
Expand All @@ -75,10 +75,12 @@ class Some {
init(double: Double) {
self.double = double
self.int = int
self.int = 0
}
static var stub: Some = Some(int: 0, double: 0.0)
static var stub: Some {
Some(int: 0, double: 0.0)
}
init(int: Int, double: Double) {
self.int = int
self.double = double
Expand Down Expand Up @@ -111,7 +113,9 @@ class Some {
self.int = int
}
static var stub: Some = Some(double: 0.0, int: 0)
static var stub: Some {
Some(double: 0.0, int: 0)
}
}
"""

Expand Down Expand Up @@ -140,7 +144,9 @@ class Some {
self.double = double
}
static var stub: Some = Some(int: 0, double: 0.0)
static var stub: Some {
Some(int: 0, double: 0.0)
}
}
"""

Expand All @@ -159,7 +165,9 @@ class Some {
var double: Double
let string: String = ""
static var stub: Some = Some(int: 0, double: 0.0)
static var stub: Some {
Some(int: 0, double: 0.0)
}
init(int: Int, double: Double) {
self.int = int
self.double = double
Expand All @@ -182,6 +190,8 @@ struct Some {
var double: Double
let string: String = ""
static var stub: Some = Some(int: 0, double: 0.0)
static var stub: Some {
Some(int: 0, double: 0.0)
}
}
"""

0 comments on commit 6d3c566

Please sign in to comment.