Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct the throws clause in the closure within template logic to support TypedThrow. #262

Merged
merged 30 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
199c2ef
Update swift-syntax to 600.0.0-prerelease
fummicc1 Jun 30, 2024
aa0e097
Resolve warnings for SwiftSyntax600
fummicc1 Jun 30, 2024
2e7259b
Update for tests
fummicc1 Jun 30, 2024
725c67d
update to support typed-throw
fummicc1 Jun 30, 2024
7f7028a
Update Sources/MockoloFramework/Parsers/SwiftSyntaxExtensions.swift
fummicc1 Aug 3, 2024
e3a2da8
Read accessor and omit setCallCount if protocol has no setter
sidepelican Oct 25, 2024
2a7a57d
Remove unnecessary static var handling
sidepelican Oct 25, 2024
96add24
Support get async and get throws property accessor
sidepelican Oct 25, 2024
72a125d
small rename and remove unused code
sidepelican Oct 25, 2024
0194530
generate initialize for computed var
sidepelican Oct 25, 2024
3acc4a7
computed getter handles with the same way of method
sidepelican Oct 25, 2024
c28c027
remove deprecated method
sidepelican Oct 25, 2024
0028467
Add test for throwing never
sidepelican Oct 25, 2024
802bed7
small formatting
sidepelican Oct 25, 2024
ee6da9a
Merge remote-tracking branch 'origin/master' into feature/issue-261-t…
fummicc1 Oct 26, 2024
c011048
Define FunctionSuffixClause.
fummicc1 Oct 26, 2024
62cbd3c
Change swift-syntax organization from apple to swiftlang
fummicc1 Oct 26, 2024
909d26e
Define FunctionSuffixClause
fummicc1 Oct 26, 2024
75a0f36
Update TestCase
fummicc1 Oct 26, 2024
bac0c69
refactoring
fummicc1 Oct 26, 2024
f4406dd
Merge branch 'property_accessor' into feature/issue-261-typed-throw
fummicc1 Oct 26, 2024
fa5ccbb
Merge remote-tracking branch 'origin/master' into feature/issue-261-t…
fummicc1 Oct 26, 2024
c004716
fix: remove unused string token.
fummicc1 Oct 26, 2024
de89895
Fix for typed throws
fummicc1 Oct 26, 2024
1b1de5d
rename argument for applyThrowingTemplate method. Add doc comment
fummicc1 Oct 26, 2024
f112110
Avoid to expose special parameter in a common method.
fummicc1 Oct 27, 2024
71d6920
Update TestFixture
fummicc1 Oct 27, 2024
733771e
Keep applyThrowingTemplate nullable to consider trivia.
fummicc1 Oct 27, 2024
be998e1
Refactor template logic for closure's suffix.
fummicc1 Oct 27, 2024
4a3a54a
Refactor function's suffix logic.
fummicc1 Oct 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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",
sidepelican marked this conversation as resolved.
Show resolved Hide resolved
"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
)

Copy link
Collaborator

@sidepelican sidepelican Oct 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It want to avoid relying on internal implementations.

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

(This snippet exists in the other 2 places. Maybe it's a time to add utility, not must)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds nice! I fixed it in these 2 commits.

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))
}
"""

sidepelican marked this conversation as resolved.
Show resolved Hide resolved
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
sidepelican marked this conversation as resolved.
Show resolved Hide resolved
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
)
}
}