CodeReview之SwiftLint

一、前言

  • SwiftLintRealm 推出的一款 Swift 代碼規(guī)范檢查工具,SwiftLint 是基于 GitHub 公布的 Swift代碼規(guī)范 對 Swift 代碼進(jìn)行檢查的。
  • GitHub 公布的 Swift 代碼規(guī)范 - 原文
  • GitHub 公布的 Swift 代碼規(guī)范 - 中文
  • 配置好 SwiftLint 之后,在 Xcode 中直接編譯代碼,SwiftLint 就會按照預(yù)先設(shè)置好的代碼規(guī)范自動檢查代碼,不符合規(guī)范的代碼就會通過警告(warning)或者報(bào)錯(cuò)(error)的形式指示給開發(fā)者,從而對開發(fā)者的代碼進(jìn)行規(guī)范。
  • 除了 SwiftLint 自帶的規(guī)則之外,開發(fā)者還可以自定義規(guī)則。同時(shí)可以禁用或啟用某一些規(guī)則。

二、安裝 SwiftLint

SwiftLint 可以通過 3 種方式進(jìn)行安裝:

  • 通過 HomeBrew 安裝
  • 通過 CocoaPods 安裝
  • 通過 pkg 安裝包安裝

1、通過 Homebrew 安裝【全局安裝】

  • 第一步: 安裝 Homebrew (如已安裝,請?zhí)^)
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

如果出現(xiàn)下圖所示,表示 Homebrew 安裝成功。

Homebrew安裝成功.png
  • 第二步: 通過終端命令安裝 SwiftLint
brew install SwiftLint
SwiftLint 安裝成功.png

2、通過 CocoaPods 安裝【局部安裝】

  • 通過 CocoaPods 安裝,只對單個(gè)項(xiàng)目有效,如果想要對不同的項(xiàng)目使用不同的 SwiftLint 版本,這會是一種很好的解決方案。
  • 需要注意的是使用這種方案會將整個(gè) SwiftLint 以及它的依賴包的完整資源文件都安裝到 Pods/ 目錄中去,所以在使用代碼版本管理工具比如 git/svn 時(shí)要注意設(shè)置忽略(ignore)相關(guān)目錄。
  • 通過 CocoaPods 安裝 SwiftLint,跟安裝第三方框架一樣。
  • 在項(xiàng)目根目錄創(chuàng)建 Podfile
pod 'SwiftLint'

3、通過安裝包安裝【全局安裝】

SwiftLint 還支持使用 pkg 安裝包進(jìn)行安裝,在官方的 GitHub 頁面可以找到最新發(fā)布的安裝包

SwiftLint 安裝包.png

三、查看 SwiftLint 的全部命令

  • 在終端中輸入 swiftlint help
swiftlint help
SwiftLint 的全部命令.png
  • 各個(gè)命令注釋:
# Automatically correct warnings and errors
# 自動更改警告和錯(cuò)誤(僅適用于支持自動更改的規(guī)則)
autocorrect     

# Generates markdown documentation for all rules
# 為所有規(guī)則生成 markdown 文檔
generate-docs     
 
# Display general or command-specific help
# 顯示通用命令或指定命令的幫助信息
help          
 
# Print lint warnings and errors (default command) 
# 打印輸出所有的警告和錯(cuò)誤
lint     

# Display the list of rules and their identifiers    
# 顯示所有規(guī)則的列表以及對應(yīng)的 ID   
rules      
  
# Display the current version of SwiftLint   
# 顯示 SwiftLint 的當(dāng)前版本號
version         

四、SwiftLint 的使用

安裝完成之后,需要在Xcode中配置相關(guān)設(shè)置,才能使 SwiftLint 在 Xcode 中自動檢測代碼規(guī)范。配置也很簡單,只需要在 Xcode 的 Build Phases 中新建一個(gè) Run Script Phase 配置項(xiàng),在里面添加相關(guān)代碼后,編譯即可!

1、SwiftLint 腳本設(shè)置

  • 這里分兩種情況: 全局腳本的添加 和 局部腳本的添加。

(1)全局腳本的添加

  • 全局腳本
if which swiftlint >/dev/null; then
  swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
  • 添加全局腳本的步驟


    添加全局腳本的步驟.png
  • 如果沒有安裝 SwiftLint,則會報(bào)出警告,提示團(tuán)隊(duì)成員安裝 SwiftLint
Shell Script Invocation Warning:
warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint

(2)局部腳本的添加

  • 局部腳本
"${PODS_ROOT}/SwiftLint/swiftlint"
  • 添加局部腳本的步驟


    添加局部腳本的步驟.png
  • 這里其實(shí)是設(shè)置了一個(gè)自動編譯腳本,每次運(yùn)行編譯都會自動執(zhí)行這個(gè)腳本。
  • 如果正確安裝了 SwiftLint,就會執(zhí)行 SwiftLint 中的代碼規(guī)范檢查,如果沒有安裝,腳本會拋出一個(gè)沒有安裝 SwiftLint 并提示下載的錯(cuò)誤,方便提醒團(tuán)隊(duì)中沒有安裝的成員。
Shell Script Invocation Error: 
swiftlint: No such file or directory
  • 在沒有安裝 SwiftLint 的情況下,如不想直接報(bào)錯(cuò),可以使用如下腳本:
"${PODS_ROOT}/SwiftLint/swiftlint"
echo "warning: ..."

2、SwiftLint 的體驗(yàn)

  • 新建一個(gè) SwiftLintDemo 的工程,配置完成后,Command + B 編譯
    SwiftLintDemo 新建項(xiàng)目.png
  • 如圖,新建項(xiàng)目,任何代碼都沒寫,直接報(bào)出一堆 警告,甚至還有 錯(cuò)誤。試想,如果是正在開發(fā)中的項(xiàng)目,你可能會發(fā)現(xiàn)你的項(xiàng)目提示N+的黃色警告和N+的紅色錯(cuò)誤。
  • 通過 SwiftLintDemo,你會發(fā)現(xiàn)甚至一些空格和一些系統(tǒng)的方法和注釋也會報(bào)錯(cuò)或者警告。
  • SwiftLint 默認(rèn)方法名或者注釋不得超過120個(gè)字符。
  • SwiftLint 的所有規(guī)則可以在: Rules 找到。

五、自定義配置

  • 當(dāng)我們編譯一個(gè)正在開發(fā)的項(xiàng)目代碼后,看到的 N 多的警告和錯(cuò)誤,其實(shí)并不全都需要我們來解決,因?yàn)檫@里面通常包含了第三方庫的代碼規(guī)范問題,而且好多問題的級別都被設(shè)置成了 error。
  • 第三方庫的代碼規(guī)范問題,這不是我們的問題,怎么解決?
  • 因此,我們需要做一些設(shè)置,讓 SwiftLint 在做代碼規(guī)范檢查的時(shí)候自動忽略 CocoaPods、Carthage 等包管理器引入的第三方庫(當(dāng)然,手動導(dǎo)入的第三方庫也能設(shè)置忽略)。
  • 上面的問題需要我們來 自定義配置文件

1、創(chuàng)建配置文件

  • 首先,需要在項(xiàng)目的根目錄下新建一個(gè)名為 .swiftlint.yml 的配置文件。

  • 打開終端,cd 進(jìn)入項(xiàng)目根目錄下。

  • 輸入: touch .swiftlint.yml

    創(chuàng)建 .swiftlint.yml文件.png

  • 執(zhí)行完命令之后,在文件夾中就會有一個(gè) .swiftlint.yml 的隱藏文件。

  • 隱藏/顯示隱藏文件的命令: Command + Shift + .

    隱藏的配置文件.png

  • 下面來認(rèn)識一下主要的幾個(gè)配置選項(xiàng)

disabled_rules: # 禁用指定的規(guī)則
  - colon
  - comma
  - control_statement
opt_in_rules: # 啟用指定的規(guī)則
  - empty_count
  - missing_docs
  # 可以通過執(zhí)行如下指令來查找所有可用的規(guī)則:
  # swiftlint rules
included: # 執(zhí)行 linting 時(shí)包含的路徑。如果出現(xiàn)這個(gè) `--path` 會被忽略。
  - Source
excluded: # 執(zhí)行 linting 時(shí)忽略的路徑。 優(yōu)先級比 `included` 更高。
  - Carthage
  - Pods
  - Source/ExcludedFolder
  - Source/ExcludedFile.swift

2、在代碼中關(guān)閉某個(gè)規(guī)則

  • 可以通過在一個(gè)源文件中定義一個(gè)如下格式的注釋來關(guān)閉這個(gè)規(guī)則
// swiftlint:disable <rule>
  • 在該文件結(jié)束之前或者在定義如下格式的匹配注釋之前,這條規(guī)則都會被禁用:
// swiftlint:enable <rule>
  • 舉例: viewDidLoad方法后面的圓括號 () 跟 大括號 { 貼在了一起
    // swiftlint:disable opening_brace
    override func viewDidLoad(){ 
        // swiftlint:enable opening_brace
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

規(guī)則關(guān)閉之前:

規(guī)則關(guān)閉之前.png

規(guī)則關(guān)閉之后:

規(guī)則關(guān)閉之后.png
  • 也可以通過添加 :previous, :this 或者 :next 來使關(guān)閉或者打開某條規(guī)則的命令分別應(yīng)用于前一行,當(dāng)前或者后一行代碼。
// swiftlint:disable:next force_cast
let noWarning = NSNumber() as! Int
let hasWarning = NSNumber() as! Int
let noWarning2 = NSNumber() as! Int // swiftlint:disable:this force_cast
let noWarning3 = NSNumber() as! Int
// swiftlint:disable:previous force_cast

規(guī)則關(guān)閉之前:

規(guī)則關(guān)閉之前.png

規(guī)則關(guān)閉之后:

規(guī)則關(guān)閉之后.png

3、忽略引入的第三方庫

excluded 配置選項(xiàng)用來設(shè)置忽略代碼規(guī)范檢查的路徑,可以指定整個(gè)文件夾。

  • 忽略 CocoaPods 引入的第三方庫
excluded: 
  - Pods
  • 如果你的項(xiàng)目中使用 Carthage 管理第三方庫,可以將 Carthage 目錄添加到忽略列表:
excluded:
  - Pods
  - Carthage
  • 指定精確路徑下的文件,通過 - xxx 的形式列在下面就可以了。
excluded: # 執(zhí)行 linting 時(shí)忽略的路徑。優(yōu)先級比 `included` 更高。
  - Source/ExcludedFolder
  - Source/ExcludedFile.swift

4、嵌套配置

SwiftLint 支持通過嵌套配置文件的方式來對代碼分析過程進(jìn)行更加細(xì)致的控制。

  • 在項(xiàng)目的 根 .swiftlint.yml 文件里設(shè)置 user_nested_configs: true 值。
  • 在目錄結(jié)構(gòu)必要的地方引入額外的 .swiftlint.yml 文件。
  • 每個(gè)文件被檢查時(shí)會使用在文件所在目錄下的或者父目錄的更深層目錄下的配置文件。否則根配置文件將會生效。
  • excluded,includeduse_nested_configs 在嵌套結(jié)構(gòu)中會被忽略。

5、自動更正

  • Swiftlint 可以自動修正某些錯(cuò)誤,磁盤上的文件會被一個(gè)修正后的版本覆蓋。
  • 請確保在對文件執(zhí)行 swiftlint autocorrect 之前有對它們做過備份,否則的話有可能導(dǎo)致重要數(shù)據(jù)的丟失。
  • 因?yàn)樵趫?zhí)行自動更正修改某個(gè)文件后,很有可能導(dǎo)致之前生成的代碼檢查信息無效或者不正確,所以當(dāng)在執(zhí)行代碼更正時(shí)標(biāo)準(zhǔn)的檢查是無法使用的。

官方示例

disabled_rules: # rule identifiers to exclude from running
  - colon
  - comma
  - control_statement
opt_in_rules: # some rules are only opt-in
  - empty_count
  # Find all the available rules by running:
  # swiftlint rules
included: # paths to include during linting. `--path` is ignored if present.
  - Source
excluded: # paths to ignore during linting. Takes precedence over `included`.
  - Carthage
  - Pods
  - Source/ExcludedFolder
  - Source/ExcludedFile.swift

# configurable rules can be customized from this configuration file
# binary rules can set their severity level
force_cast: warning # implicitly
force_try:
  severity: warning # explicitly
# rules that have both warning and error levels, can set just the warning level
# implicitly
line_length: 110
# they can set both implicitly with an array
type_body_length:
  - 300 # warning
  - 400 # error
# or they can set both explicitly
file_length:
  warning: 500
  error: 1200
# naming rules can set warnings/errors for min_length and max_length
# additionally they can set excluded names
type_name:
  min_length: 4 # only warning
  max_length: # warning and error
    warning: 40
    error: 50
  excluded: iPhone # excluded via string
identifier_name:
  min_length: # only min_length
    error: 4 # only error
  excluded: # excluded via string array
    - id
    - URL
    - GlobalAPIKey
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji)

最后

原文鏈接
譯文鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明AI閱讀 16,210評論 3 119
  • 我們常常說,在大學(xué)面臨選擇的時(shí)候,父母為你鋪的路,不一定是你最想要的。長輩們給的建議,不一定是你最心之神往的。所有...
    家以純閱讀 352評論 0 8
  • 夢境是冥冥之中的注定。如果不寫下來就會忘記,不管夢里的事物有多么真實(shí);不管夢里的你愛的多么深。 初次看到《你的名字...
    Marssi閱讀 985評論 0 1
  • 中性筆+油畫棒 下班后和朋友逛街。 本沒打算買包,偏偏那家店要開在下班必經(jīng)路上。 進(jìn),看,買,走,十分鐘不到。 原...
    巫落閱讀 212評論 0 0

友情鏈接更多精彩內(nèi)容