Skip to content

Commit

Permalink
Correct the throws clause in the closure within template logic to s…
Browse files Browse the repository at this point in the history
…upport TypedThrow. (#262)

* Update swift-syntax to 600.0.0-prerelease

* Resolve warnings for SwiftSyntax600

* Update for tests

* update to support typed-throw

* Update Sources/MockoloFramework/Parsers/SwiftSyntaxExtensions.swift

Co-authored-by: Iceman <[email protected]>

* Read accessor and omit setCallCount if protocol has no setter

* Remove unnecessary static var handling

* Support get async and get throws property accessor

* small rename and remove unused code

* generate initialize for computed var

* computed getter handles with the same way of method

* remove deprecated method

* Add test for throwing never

* small formatting

* Define FunctionSuffixClause.

* Change swift-syntax organization from apple to swiftlang

* Define FunctionSuffixClause

* Update TestCase

* refactoring

* fix: remove unused string token.

* Fix for typed throws

* rename argument for applyThrowingTemplate method. Add doc comment

* Avoid to expose special parameter in a common method.

* Update TestFixture

* Keep applyThrowingTemplate nullable to consider trivia.
review comment: #262 (comment)

* Refactor template logic for closure's suffix.

* Refactor function's suffix logic.

---------

Co-authored-by: Iceman <[email protected]>
Co-authored-by: Iceman <[email protected]>
  • Loading branch information
3 people authored Oct 27, 2024
1 parent 2628c64 commit 09a1ea2
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax.git",
"location" : "https://github.com/swiftlang/swift-syntax.git",
"state" : {
"revision" : "0687f71944021d616d34d922343dcef086855920",
"version" : "600.0.1"
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ let package = Package(
.library(name: "MockoloFramework", targets: ["MockoloFramework"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax.git", from: "600.0.1"),
.package(url: "https://github.com/swiftlang/swift-syntax.git", from: "600.0.1"),
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.5.0"),
],
targets: [
Expand Down
2 changes: 2 additions & 0 deletions Sources/MockoloFramework/Models/ClosureModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ final class ClosureModel: Model {
}

init(name: String, genericTypeParams: [ParamModel], paramNames: [String], paramTypes: [SwiftType], isAsync: Bool, throwing: ThrowingKind, returnType: SwiftType, encloser: String) {
// In the mock's call handler, rethrows is unavailable.
let throwing = throwing.coerceRethrowsToThrows
self.name = name + .handlerSuffix
self.isAsync = isAsync
self.throwing = throwing
Expand Down
10 changes: 10 additions & 0 deletions Sources/MockoloFramework/Models/ThrowingKind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,13 @@ enum ThrowingKind: Equatable {
}
}
}

extension ThrowingKind {
/// Replace rethrows with throws.
var coerceRethrowsToThrows: ThrowingKind {
if case .rethrows = self {
return .any
}
return self
}
}
8 changes: 4 additions & 4 deletions Sources/MockoloFramework/Templates/MethodTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ extension MethodModel {
let handlerVarType = handler.type.typeName // ?? "Any"
let handlerReturn = handler.render(with: identifier, encloser: "") ?? ""

let suffixStr = [
isAsync ? String.async : nil,
throwing.applyThrowingTemplate(),
].compactMap { $0 }.joined(separator: " ") + " "
let suffixStr = applyFunctionSuffixTemplate(
isAsync: isAsync,
throwing: throwing
)
let returnStr = returnTypeName.isEmpty ? "" : "-> \(returnTypeName)"
let staticStr = isStatic ? String.static + " " : ""
let keyword = isSubscript ? "" : "func "
Expand Down
8 changes: 4 additions & 4 deletions Sources/MockoloFramework/Templates/NominalTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,10 @@ extension NominalModel {
let genericTypeDeclsStr = m.genericTypeParams.compactMap {$0.render(with: "", encloser: "")}.joined(separator: ", ")
let genericTypesStr = genericTypeDeclsStr.isEmpty ? "" : "<\(genericTypeDeclsStr)>"
let paramDeclsStr = m.params.compactMap{$0.render(with: "", encloser: "")}.joined(separator: ", ")
let suffixStr = [
m.isAsync ? String.async : nil,
m.throwing.applyThrowingTemplate(),
].compactMap { $0 }.joined(separator: " ") + " "
let suffixStr = applyFunctionSuffixTemplate(
isAsync: m.isAsync,
throwing: m.throwing
)

if override {
let paramsList = m.params.map { param in
Expand Down
25 changes: 25 additions & 0 deletions Sources/MockoloFramework/Utils/FunctionSuffixTemplate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Copyright (c) 2018. Uber Technologies
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/// Apply template for function suffix
///
/// Suffix consists of async and throws.
func applyFunctionSuffixTemplate(isAsync: Bool, throwing: ThrowingKind) -> String {
[
isAsync ? String.async : nil,
throwing.applyThrowingTemplate(),
].compactMap { $0 }.joined(separator: " ") + " "
}
8 changes: 4 additions & 4 deletions Sources/MockoloFramework/Utils/TypeParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,10 @@ public final class SwiftType {
displayableReturnType = "(\(displayableReturnType))"
}

let suffixStr = [
isAsync ? String.async + " " : nil,
throwing.hasError ? String.throws + " " : nil,
].compactMap { $0 }.joined()
let suffixStr = applyFunctionSuffixTemplate(
isAsync: isAsync,
throwing: throwing
)

let typeStr = "((\(displayableParamStr)) \(suffixStr)-> \(displayableReturnType))?"
return SwiftType(typeStr, cast: returnTypeCast)
Expand Down
66 changes: 55 additions & 11 deletions Tests/TestFuncs/TestFuncThrow/FixtureFuncThrow.swift
Original file line number Diff line number Diff line change
@@ -1,35 +1,29 @@
import MockoloFramework


let funcThrow2 = """
import Foundation
/// \(String.mockAnnotation)
protocol FuncThrow {
func update<T>(arg1: T, arg2: () throws -> T) rethrows -> T
func update<T, U>(arg1: T, arg2: @escaping (U) throws -> ()) throws -> ((T) -> (U))
}
"""

let funcThrow = """
import Foundation
/// \(String.mockAnnotation)
protocol FuncThrow {
func f1(arg: Int) throws -> String
func f2(arg: Int) throws
func f3(arg: Int) throws(SomeError)
func f4(arg: Int) throws(SomeError) -> String
func f5() throws (MyError)
func f6() async throws (any Error)
func g1(arg: (Int) throws -> ())
throws -> String
func g2(arg: (Int) throws -> ()) throws
func h(arg: (Int) throws -> ()) rethrows -> String
func h2(arg: (Int) throws(SomeError) -> ()) rethrows -> String
func update<T, U>(arg1: T, arg2: @escaping (U) throws -> ()) throws -> ((T) -> (U))
func update<T>(arg1: T, arg2: () throws -> T) rethrows -> T
}
"""

let funcThrowMock =
"""
import Foundation
Expand Down Expand Up @@ -57,6 +51,46 @@ class FuncThrowMock: FuncThrow {
}
private(set) var f3CallCount = 0
var f3Handler: ((Int) throws(SomeError) -> ())?
func f3(arg: Int) throws(SomeError) {
f3CallCount += 1
if let f3Handler = f3Handler {
try f3Handler(arg)
}
}
private(set) var f4CallCount = 0
var f4Handler: ((Int) throws(SomeError) -> (String))?
func f4(arg: Int) throws(SomeError) -> String {
f4CallCount += 1
if let f4Handler = f4Handler {
return try f4Handler(arg)
}
return ""
}
private(set) var f5CallCount = 0
var f5Handler: (() throws(MyError) -> ())?
func f5() throws(MyError) {
f5CallCount += 1
if let f5Handler = f5Handler {
try f5Handler()
}
}
private(set) var f6CallCount = 0
var f6Handler: (() async throws(any Error) -> ())?
func f6() async throws(any Error) {
f6CallCount += 1
if let f6Handler = f6Handler {
try await f6Handler()
}
}
private(set) var g1CallCount = 0
var g1Handler: (((Int) throws -> ()) throws -> (String))?
func g1(arg: (Int) throws -> ()) throws -> String {
Expand Down Expand Up @@ -87,6 +121,16 @@ class FuncThrowMock: FuncThrow {
return ""
}
private(set) var h2CallCount = 0
var h2Handler: (((Int) throws(SomeError) -> ()) throws -> (String))?
func h2(arg: (Int) throws(SomeError) -> ()) rethrows -> String {
h2CallCount += 1
if let h2Handler = h2Handler {
return try h2Handler(arg)
}
return ""
}
private(set) var updateCallCount = 0
var updateHandler: ((Any, Any) throws -> (Any))?
func update<T, U>(arg1: T, arg2: @escaping (U) throws -> ()) throws -> ((T) -> (U)) {
Expand Down
40 changes: 40 additions & 0 deletions Tests/TestInit/FixtureInit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,43 @@ class MyProtocolMock: MyProtocol {
}
"""

let throwableInit = """
/// \(String.mockAnnotation)
protocol MyProtocol {
init(param: String) throws
}
"""

let throwableInitMock = """
class MyProtocolMock: MyProtocol {
private var _param: String!
init() { }
required init(param: String = "") throws {
self._param = param
}
}
"""

let typedThrowableInit = """
/// \(String.mockAnnotation)
protocol MyProtocol {
init(param: String) throws(SomeError)
}
"""

let typedThrowableInitMock = """
class MyProtocolMock: MyProtocol {
private var _param: String!
init() { }
required init(param: String = "") throws(SomeError) {
self._param = param
}
}
"""
14 changes: 14 additions & 0 deletions Tests/TestInit/InitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,18 @@ class InitTests: MockoloTestCase {
dstContent: initWithSameParamNameButDifferentTypeMock
)
}

func testThrowableInit() {
verify(
srcContent: throwableInit,
dstContent: throwableInitMock
)
}

func testTypedThrowableInit() {
verify(
srcContent: typedThrowableInit,
dstContent: typedThrowableInitMock
)
}
}

0 comments on commit 09a1ea2

Please sign in to comment.