iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
自我挑戰組

自己的 Leak, 自己抓(swift)系列 第 18

判斷 Closure 是否是 Escape

  • 分享至 

  • xImage
  •  

今天我們一樣還是透過 CursorInfo 查詢

並取得 key.annotated_decl


key.annotated_decl

但是,查詢對象改為 DispatchQueue.main.asyncasync

DispatchQueue.main.async { ... }
<Declaration>
    func async(
        group: <Type usr=\"c:objc(cs)OS_dispatch_group\">DispatchGroup</Type>? = nil, 
        qos: <Type usr=\"s:8Dispatch0A3QoSV\">DispatchQoS</Type> = .unspecified, 
        flags: <Type usr=\"s:8Dispatch0A13WorkItemFlagsV\">DispatchWorkItemFlags</Type> = [], 
        execute work: @escaping @convention(block) () -> <Type usr=\"s:s4Voida\">Void</Type>
    )
</Declaration>

取得 value(原始定義)

func async(
    group: DispatchGroup? = nil, 
    qos: DispatchQos = .unspecified, 
    flags: DispatchWorkItemFlags = [], 
    execute work: @escaping @convention(block) () -> Void
)

Function Call Expr

透過解析 Function Call Expr 取得 last(index)/first name

比較麻煩的是 closure 在 function call 會有三種表示方式。

trailing closure

async {}

labeled closure

async {
} label: {
}

normal closure

async({})

Get index(name)

  • trailing closure
    • args.last
  • labeled closure
    • args["label"]
  • normal closure
    • args["label"]
    • 有可能遇到無參數名稱

遇到無參數名稱,以及有預設值情況下難以判斷

解析是否是 escape

於是我們再將定義拿去 visitor parse 一遍

func async(
    group: DispatchGroup? = nil, 
    qos: DispatchQos = .unspecified, 
    flags: DispatchWorkItemFlags = [], 
    execute work: @escaping @convention(block) () -> Void
)

取得

  • type: trailing closure
  • name: execute
  • index: last(3)
  • type: @escaping @convention(block) () -> Void

進一步 Parsing

@escaping @convention(block) () -> Void

判斷目標:

  • @escaping
  • (closure),例:
    • (() -> Void)
  • objc closure(@convention(block))

上一篇
判斷變數是 weak?
下一篇
Escaping Closure Detector
系列文
自己的 Leak, 自己抓(swift)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言