對一些特殊的 function,我們會想 skip 他
例如 DispatchQueue.main.async
我們需要取得一些很特定的屬性,才會有能力去 skip
從 typename 可以再度證明 instance function 是 curry function
refFunctionMethodInstance
a()
-> a
(A) -> () -> ()
-> A
struct A {
func a() {}
}
可以得知是 static method,且有 X.Type
的特性
refFunctionMethodStatic
a()
-> a
(A.Type) -> () -> ()
-> A
struct A {
static func a() {}
}
可以看出 A()
應該是 A.init()
的語法糖
以及定義很像 static function
refFunctionConstructor
init()
-> init
(A.Type) -> () -> A
-> A
A()
struct A {}
這邊我們實作一個很像 static function 格式的 global function
可以發現 global function 是 .refFunctionFree
refFunctionFree
a(_:)
-> a
(Any.Type) -> () -> ()
-> ``func a(_ type: Any.Type) -> () -> () {
return {}
}
這邊將 generic 以及 nested 一起說明
從 nested 角度來看 type 是 A.B
從 generic 角度來看 type 是 A<T>
從 generic & nested 角度來看 type 是 A<T>.B<U>
從使用者角度來看 A<T>.B<U>
還是改為 A.B
較為方便
refFunctionMethodStatic
a(_:)
-> a
<T, U, V> (A<T>.B<U>.Type) -> (V) -> ()
-> A<T>.B<U>
-> A.B
A<Int>.B<Int>.a(1)
struct A<T> {
struct B<U> {
static func a<V>(_ v: V) {}
}
}
可以透過 key.modulename
取得
UIView.anmiate
module 為UIKit.UIView
而不是UIKit
最後再用測試驗證我們的想法無誤
final class SkipConceptTests: XCTestCase {
final func testObjFunction() throws {
let code = """
A().a()
struct A {
func a() {}
}
"""
let client = SKClient(code: code, arguments: SDK.macosx.args)
try prepare(client: client) { client in
let res = try client(4)
XCTAssertEqual(code[4 ... 6], "a()")
XCTAssertEqual(res.name, "a()")
XCTAssertEqual(res.typename, "(A) -> () -> ()")
XCTAssertEqual(res.kind, .refFunctionMethodInstance)
}
}
private func a(_ type: Any.Type) -> () -> () {
return {}
}
private func temp() {
let _ = a(Int.self)
}
final func testFunctionReturnClosure() throws {
let code = """
let x = a(Int.self)
func a(_ type: Any.Type) -> () -> () {
return {}
}
"""
let client = SKClient(code: code, arguments: SDK.macosx.args)
try prepare(client: client) { client in
let res = try client(8)
XCTAssertEqual(code[8 ... 18], "a(Int.self)")
XCTAssertEqual(res.name, "a(_:)")
XCTAssertEqual(res.typename, "(Any.Type) -> () -> ()")
XCTAssertEqual(res.kind, .refFunctionFree)
}
}
final func testGenericFunction() throws {
let code = """
a(t: 1)
func a<T>(t: T) {}
"""
let client = SKClient(code: code, arguments: SDK.macosx.args)
try prepare(client: client) { client in
let res = try client(0)
XCTAssertEqual(code[0 ... 6], "a(t: 1)")
XCTAssertEqual(res.name, "a(t:)")
XCTAssertEqual(res.typename, "<T> (t: T) -> ()")
XCTAssertEqual(res.kind, .refFunctionFree)
}
}
final func testStaticFunction() throws {
let code = """
A.a()
struct A {
static func a() {}
}
"""
let client = SKClient(code: code, arguments: SDK.macosx.args)
try prepare(client: client) { client in
let res = try client(2)
XCTAssertEqual(code[2 ... 4], "a()")
XCTAssertEqual(res.name, "a()")
XCTAssertEqual(res.typename, "(A.Type) -> () -> ()")
XCTAssertEqual(res.kind, .refFunctionMethodStatic)
}
}
final func testGenericNestedType() throws {
let code = """
A<Int>.B<Int>.a(1)
struct A<T> {
struct B<U> {
static func a<V>(_ v: V) {}
}
}
"""
let client = SKClient(code: code, arguments: SDK.macosx.args)
try prepare(client: client) { client in
let res = try client(14)
XCTAssertEqual(code[0 ... 17], "A<Int>.B<Int>.a(1)")
XCTAssertEqual(res.name, "a(_:)")
XCTAssertEqual(res.typename, "<T, U, V> (A<T>.B<U>.Type) -> (V) -> ()")
XCTAssertEqual(res.kind, .refFunctionMethodStatic)
}
}
final func testConstructor() throws {
let code = """
A()
struct A {}
"""
let client = SKClient(code: code, arguments: SDK.macosx.args)
try prepare(client: client) { client in
let res = try client(0)
XCTAssertEqual(code[0 ... 2], "A()")
XCTAssertEqual(res.secondary_symbols?.name, "init()")
XCTAssertEqual(res.secondary_symbols?.typename, "(A.Type) -> () -> A")
XCTAssertEqual(res.secondary_symbols?.kind, .refFunctionConstructor)
}
}
}