Translation – 起底 SourceKit

萌面大道發表於2019-03-04

For more, please visit my GitHub repo: github.com/kingcos/Per…

作者 發表時間 原文連結
JP Simard 20140706 www.jpsim.com/uncovering-…

為了支援一門奇特的新程式語言(譯者注:即 Swift),漂亮的實時 IDE 特性,以及令人印象深刻的跨語言協同性(譯者注:即 Swift 與 Obj-C),Apple 不得不開發一些新的底層工具。這裡我們將專注於 SourceKit,Xcode 背後的功臣。

SourceKitSidekick 暫時披著披肩

什麼是 SourceKit?

SourceKit 是一套工具集,使得大多數 Swift 原始碼層面的操作特性得以支援,例如原始碼解析、語法高亮、排版(typesetting)、自動補全、跨語言標頭檔案生成,等等。

架構

傳統上,Xcode 在執行時跑著其編譯器(Clang),即意味著編譯器將可能在任何時候崩潰,IDE 同樣。

Xcode 架構示意圖

更有甚者,Xcode 容易喚起編譯器進行成千上萬次解析、高亮、以及排版原始碼,所有這一切都在使用者鍵入「⌘ + B」之前。這是因為不像大多數編輯器(Vim/Sublime/…),Xcode 並不使用正規表示式解析原始碼,而是使用 Clang 強大的(也更加複雜的)解析器(parser)和標記器(tokenizer)。

慶幸的是,Xcode 6 中的 Swift 移除了該特性1,合併所有原始碼操作特性至一個獨立的程式,並和 Xcode 通過 XPC 交流:sourcekitd。無論 Xcode 6 何時載入任何 Swift 程式碼,該 XPC 守護程式將被啟動。

如果每次出現如圖情況時 Xcode 都會崩潰,生活將變得痛苦不堪

Xcode 如何使用 SourceKit

因為 SourceKit 是一個私有且無文件的工具,我們需要獲得一些小點子來學習如何使用它。通過設定 SOURCEKIT_LOGGING2 環境變數,Xcode 將記錄 SourceKit 與 stdout 間的通訊,允許我們觀察到它們的實時通訊。這就是如何發現本文中的許多命令。

統一符號解析

SourceKit 藉助 Clang 中稱作 USR(Unified Symbol Resolution,即統一符號解析)的特性,為原始碼令牌(token,例如類,屬性,方法等)對應一個唯一識別符號。這使得你可以使用 「⌘ + 點選」Xcode 編輯器中任何一處令牌,即可以導航至其定義處。USR 現在甚至更加強大了,可以跨語言(Swift/Obj-C)統一一個代表。

運作中的 USR

為了從一個 Swift 檔案(以及其位置)中列印 USR,你可以執行以下命令:

$ xcrun swift-ide-test -print-usrs -source-filename=Musician.swift
10:7 s:C14swift_ide_test8Musician
14:9 s:vC14swift_ide_test8Musician4nameSS
19:9 s:vC14swift_ide_test8Musician9birthyearSu
33:5 s:FC14swift_ide_test8MusiciancFMS0_FT4nameSS9birthyearSu_S0_
33:10 s:vFC14swift_ide_test8MusiciancFMS0_FT4nameSS9birthyearSu_S0_L_4nameSS
33:24 s:vFC14swift_ide_test8MusiciancFMS0_FT4nameSS9birthyearSu_S0_L_9birthyearSu
34:9 s:vFC14swift_ide_test8MusiciancFMS0_FT4nameSS9birthyearSu_S0_L_4selfS0_
34:21 s:vFC14swift_ide_test8MusiciancFMS0_FT4nameSS9birthyearSu_S0_L_4nameSS
35:9 s:vFC14swift_ide_test8MusiciancFMS0_FT4nameSS9birthyearSu_S0_L_4selfS0_
35:26 s:vFC14swift_ide_test8MusiciancFMS0_FT4nameSS9birthyearSu_S0_L_9birthyearSu
複製程式碼

Swift 標頭檔案生成

在 Swift 中使用「⌘ + 點選」一個定義在 Obj-C 中令牌,Xcode 將會觸發生成一個類 Swift 標頭檔案。稱其為類 Swift 是因為該生成的檔案並非有效的 Swift3,但至少顯示了等效於 Obj-C 令牌的 Swift 語法。

左:原始 Obj-C 標頭檔案,右:SourceKit 生成的類 Swift 版本

在命令列使用 SourceKit

Translation – 起底 SourceKit

主要有 3 個命令列工具允許和 SourceKit 互動:sourcekitd-testswift-ide-test,以及 swift

筆者編譯了一個帶有文件的 Shell 指令碼,其執行了許多有用的命令,例如:語法高亮,介面生成,AST 解析,還原(demangling)等。

該指令碼可在 GitHub 中獲得:GitHub Gist

第三方使用 SourceKit 的工具

因為 SourceKit 獨立於 Xcode 之外,使其可以利用以構建從 Swift IDE 到文件生成器等任何東西。

Jazzy♪♫

Translation – 起底 SourceKit

jazzy 是一個命令列工具,可以為你的 Swift 或 Obj-C 專案生成文件。其利用 SourceKit 以獲得從 Obj-C 定義令牌(例如類,屬性,方法等)的 Swift 語法。

SwiftEdit

SwiftEdit 是一款支援 Swift 檔案語法高亮的概念型編輯器。

Translation – 起底 SourceKit

SourceKit 與你

我們剛剛初探了使用 SourceKit 的可能。這些工具可以做出來處理跨語言程式碼覆蓋,或者提供支援 Swift 和 Obj-C 同時編輯的編輯器。希望本文能啟發你利用 SourceKit 開發一些什麼,並在這過程中改善我們的工具。

  • 注:
    1. Obj-C 在 Xcode 6(Beta 2)中完全沒有使用 SourceKit,仍保留了 Xcode 傳統的執行中 Clang 架構。我預計在 Xcode 6 GM 前能有所改變。
    2. 為了 SourceKit 列印日誌,使用以下命令啟動 Xcode export SOURCEKIT_LOGGING=3 && /Applications/Xcode6-Beta2.app/Contents/MacOS/Xcode
    3. 猜測:我預計一旦程式語言擁有訪問控制機制,私有 Swift 模組暴露公有介面將使用相似的語法。

Reference

相關文章