iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
自我挑戰組

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

Ref 變數的來源(key.offset)

  • 分享至 

  • xImage
  •  

今天我們要透過,對變數下 cursorInfo 取得他的原始來源。


where self

針對三種不同情況查詢 self 所在位置。

extension ReferenceTests {
    final func testSelf() throws {
        let code = """
        class A {
            var a: A {
                return self
            }
        
            func b() -> A {
                return self
            }
        
            lazy var c: A = {
                return self
            }()
        
            init() {}
        }
        """

        try prepare(code: code) { client in
            /// a
            try XCTAssertEqual(client(40).offset, 23)
            XCTAssertEqual(code[40...43], "self")
            XCTAssertEqual(code[23], "{")
            
            /// b
            try XCTAssertEqual(client(87).offset, 61)
            XCTAssertEqual(code[87...90], "self")
            XCTAssertEqual(code[61...68], "b() -> A")
            
            /// c
            try XCTAssertEqual(client(136).offset, 112)
            XCTAssertEqual(code[136...139], "self")
            XCTAssertEqual(code[112...115], "c: A")
        }
    }
}

從第一個 computed var a 可以蒐集到一些有用的資訊。

  • key.offset
    • 來源在 offset 23
  • key.kind
    • local: 是區域變數
    • ref: 是參考(reference)
  • key.typename
    • 型態是 A
// var a: A {
//     return self
// }
po client(40)
- key : "key.offset"
- value : 23
- key : "key.kind"
- value : "source.lang.swift.ref.var.local"
- key : "key.typename"
- value : "A"

應此我們可以知道 self 的來源位置

https://ithelp.ithome.com.tw/upload/images/20230927/20158030c1RPF18a7X.png


Capture List

extension ReferenceTests {
    final func testCapture() throws {
        let code = """
        class A {
            func example()  {
                let a = A()
                let b: () -> () = { [aa = a, a, weak self, this = self] in
                    print(aa, a, self, this)
                }
            }
        
            init() {}
        }
        """

        /// reference of capture list
        try prepare(code: code) { client in
            /// aa = a, `a`
            try XCTAssertEqual(client(86).offset, 44)
            XCTAssertEqual(code[86], "a")
            XCTAssertEqual(code[44], "a")
            
            /// a, `a`
            try XCTAssertEqual(client(89).offset, 89)
            XCTAssertEqual(code[89], "a")
        }
        
        /// reference to capture list
        try prepare(code: code) { client in
            /// aa
            try XCTAssertEqual(client(137).offset, 81)
            /// a
            try XCTAssertEqual(client(141).offset, 89)
            /// self
            try XCTAssertEqual(client(144).offset, 97)
            /// this
            try XCTAssertEqual(client(150).offset, 103)
        }
    }

https://ithelp.ithome.com.tw/upload/images/20230927/20158030Vgg7IXc2sn.png

從這個例子可以看到

let a = A()
let b: () -> () = { [aa = a/*1*/, a/*2*/] in
    print(aa, a)
}

L3.aa 指向 L2.aa
L2.a1 指向 L1.a
是符合預期的。

但是 L2.a2 是指向 L2.a2
也就是說我們無法透過 cursorInfo 查詢到 L2.a2 的原始來源
除非,我們將 [a2] 改寫成 [a = a]([a2 = a3])


上一篇
再次面對 SourceKitten(CursorInfo)
下一篇
除非,我們今天將 `[a]` 改寫成 `[a = a]`
系列文
自己的 Leak, 自己抓(swift)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言