SwiftLint
一个旨在强制执行Swift样式和约定的工具,松散基于已归档的GitHub Swift样式指南。SwiftLint强制执行Swift社区普遍接受的样式指南规则。这些规则在Ray Wenderlich的Swift样式指南等流行样式指南中有很好的描述。
SwiftLint hook into Clang和SourceKit,以使用源文件的AST表示来获得更准确的结果。
本项目遵守贡献者行为准则。通过参与,你将期望遵守此准则。如遇到不适当行为,请向[email protected]举报。
安装
Homebrew
使用brew install swiftlint
使用 CocoaPods
仅需在您的 Podfile 中添加以下行
pod 'SwiftLint'
这将在您的下次执行 pod install
时下载 SwiftLint 二进制文件及其依赖项到 Pods/
目录下,并允许您在脚本的构建阶段通过 ${PODS_ROOT}/SwiftLint/swiftlint
调用它。
这是推荐安装特定版本 SwiftLint 的方法,因为它支持安装固定版本而不是简单地安装最新版本(这与 Homebrew 的情况不同)。
请注意,这将在 Pods/
目录中添加 SwiftLint 的二进制文件、其依赖项的二进制文件和 Swift 二进制库分配合集,因此不建议将该目录存入版本控制管理系统中,如 git。
Mint
使用$ mint install realm/SwiftLint
使用预构建包
您还可以通过从 最新 GitHub 发布版下载 SwiftLint.pkg
并运行它来安装 SwiftLint。
从源代码安装
您也可以通过克隆此项目并运行 make install
从源代码构建和安装(Xcode 12.5 或更高版本)。
用法
演示文稿
要了解将SwiftLint集成到您项目中的推荐方法的高级概述,我们鼓励您观看此演示文稿或阅读文稿。
Xcode
将SwiftLint集成到您的Xcode项目中,以便在问题导航器中显示警告和错误。
为此,请单击文件导航器中的“项目”,然后单击主应用程序目标,转到“构建阶段”。单击+并选择“新建运行脚本阶段”。以下脚本作为脚本插入:
export PATH="$PATH:/opt/homebrew/bin"
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
您可能希望将SwiftLint阶段直接移动到“编译源”步骤之前,以便在编译前快速检测错误。但是,SwiftLint设计为在有效Swift代码上运行,该代码干净地完成了编译器的解析阶段。所以,在“编译源”之前运行SwiftLint可能会产生一些不正确的结果。
如果您希望修复违规行为,脚本可以运行swiftlint --fix && swiftlint
而不是仅仅swiftlint
。这意味着所有可修复的违规都会被修复,同时确保警告在项目中显示剩余违规。
如果您通过CocoaPods安装了SwiftLint,脚本应如下所示:
"${PODS_ROOT}/SwiftLint/swiftlint"
保存时格式化Xcode插件
要使Xcode在保存时运行swiftlint --fix
,请从Alcatraz安装SwiftLintXcode插件。
AppCode
要将SwiftLint集成到AppCode中,请安装此插件,并在插件的首选项中配置SwiftLint的安装路径。通过⌥⏎
可使用fix
操作。
Atom
要将 SwiftLint 与 Atom 集成,请从 APM 安装linter-swiftlint
软件包。
Visual Studio Code
要将 SwiftLint 与 vscode 集成,请从市场安装vscode-swiftlint
扩展。
fastlane
可以使用官方 swiftlint fastlane 行动将 SwiftLint 作为 fastlane 流程的一部分运行。
swiftlint(
mode: :lint, # SwiftLint mode: :lint (default) or :autocorrect
executable: "Pods/SwiftLint/swiftlint", # The SwiftLint binary path (optional). Important if you've installed it via CocoaPods
path: "/path/to/lint", # Specify path to lint (optional)
output_file: "swiftlint.result.json", # The path of the output file (optional)
reporter: "json", # The custom reporter to use (optional)
config_file: ".swiftlint-ci.yml", # The path of the configuration file (optional)
files: [ # List of files to process (optional)
"AppDelegate.swift",
"path/to/project/Model.swift"
],
ignore_exit_status: true, # Allow fastlane to continue even if SwiftLint returns a non-zero exit status (Default: false)
quiet: true, # Don't print status logs like 'Linting ' & 'Done linting' (Default: false)
strict: true # Fail on warnings? (Default: false)
)
Docker
swiftlint
也可作为使用 Ubuntu
的 Docker 镜像使用。所以您只需第一次使用以下命令拉取 Docker 镜像
docker pull ghcr.io/realm/swiftlint:latest
然后,以后您可以像这样在 Docker 中运行《code>swiftlint
docker run -it -v `pwd`:`pwd` -w `pwd` ghcr.io/realm/swiftlint:latest
这将在此处您所在的文件夹中执行《code>swiftlint(《code>pwd),并显示如下输出
$ docker run -it -v `pwd`:`pwd` -w `pwd` ghcr.io/realm/swiftlint:latest
Linting Swift files in current working directory
Linting 'RuleDocumentation.swift' (1/490)
...
Linting 'YamlSwiftLintTests.swift' (490/490)
Done linting! Found 0 violations, 0 serious in 490 files.
有关使用的更多文档,请参阅Docker Images。
Command Line
$ swiftlint help
OVERVIEW: A tool to enforce Swift style and conventions.
USAGE: swiftlint <subcommand>
OPTIONS:
--version Show the version.
-h, --help Show help information.
SUBCOMMANDS:
analyze Run analysis rules
docs Open SwiftLint documentation website in the default web browser
generate-docs Generates markdown documentation for all rules
lint (default) Print lint warnings and errors
rules Display the list of rules and their identifiers
version Display the current version of SwiftLint
See 'swiftlint help <subcommand>' for detailed help.
在包含要检查的 Swift 文件的目录中运行 swiftlint
。将按递归方式搜索目录。
当使用 lint
或 analyze
时指定文件列表(例如由 Xcode 插件 ExtraBuildPhase
指定的 Xcode 中修改的文件列表,或基于 git ls-files -m
的工作树中的修改文件),可以通过传递选项 --use-script-input-files
并设置以下实例变量来实现:SCRIPT_INPUT_FILE_COUNT
和 SCRIPT_INPUT_FILE_0
、SCRIPT_INPUT_FILE_1
...SCRIPT_INPUT_FILE_{SCRIPT_INPUT_FILE_COUNT - 1}
。
这些是用于 自定义 Xcode 脚本阶段 输入文件的相同环境变量。
使用多个 Swift 版本
SwiftLint 集成到 SourceKit 中,因此即使 Swift 发生变化,它也可以继续工作!
这也使 SwiftLint 保持精简,因为它不需要与完整的 Swift 编译器一起发货,它只是与您已安装在机器上的官方编译器进行通信。
您应始终使用编译代码时使用的相同工具链运行 SwiftLint。
如果您有多个工具链或 Xcode 安装,则可能需要覆盖 SwiftLint 的默认 Swift 工具链。
以下是 SwiftLint 确定要使用的 Swift 工具链的顺序
$XCODE_DEFAULT_TOOLCHAIN_OVERRIDE
$TOOLCHAIN_DIR
或$TOOLCHAINS
xcrun -find swift
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
~/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
~/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
sourcekitd.framework
预期将位于上面路径中传入的值的 usr/lib/
子目录中。
您还可以将 TOOLCHAINS
环境变量设置为反向 DNS 表示法,以标识 Swift 工具链版本。
$ TOOLCHAINS=com.apple.dt.toolchain.Swift_2_3 swiftlint --fix
在 Linux 上,SourceKit 预期位于 /usr/lib/libsourcekitdInProc.so
或由 LINUX_SOURCEKIT_LIB_PATH
环境变量指定。
pre-commit
SwiftLint 可用作 pre-commit 钩子。一旦 安装,将此添加到存储库根目录中的 .pre-commit-config.yaml
repos:
- repo: https://github.com/realm/SwiftLint
rev: 0.44.0
hooks:
- id: swiftlint
将 rev
调整为您选择的 SwiftLint 版本。
规则
SwiftLint 及 Swift 社区(包括你!)包含超过 200 条规则,并且随着时间的推移还会继续贡献更多。鼓励提交Pull 请求。
您可以在这里找到更新后的规则列表以及更多相关信息。
您还可以查看Source/SwiftLintFramework/Rules 目录,查看它们的实现。
启用规则
opt_in_rules
默认禁用(即,您必须明文在配置文件中启用它们)。
关于何时标记规则为可启用
- 可以有多个误报的规则(例如
empty_count
) - 过于缓慢的规则
- 未达成共识的规则或仅在少数情况下有用的规则(例如
force_unwrapping
)
在代码中禁用规则
您可以通过以下格式在源文件内使用注释来禁用规则
// swiftlint:disable <rule1> [<rule2> <rule3>...]
这些规则将一直禁用,直到文件结束或直到 Linter 看到匹配的启用注释
// swiftlint:enable <rule1> [<rule2> <rule3>...]
例如
// swiftlint:disable colon
let noWarning :String = "" // No warning about colons immediately after variable names!
// swiftlint:enable colon
let hasWarning :String = "" // Warning generated about colons immediately after variable names
包含 all
关键字会在 Linter 看到匹配的启用注释之前禁用所有规则
// swiftlint:disable all
// swiftlint:enable all
例如
// swiftlint:disable all
let noWarning :String = "" // No warning about colons immediately after variable names!
let i = "" // Also no warning about short identifier names
// swiftlint:enable all
let hasWarning :String = "" // Warning generated about colons immediately after variable names
let y = "" // Warning generated about short identifier names
您也可以通过附加 :previous
、:this
或 :next
来修改 disable
或 enable
命令,分别将命令应用于前一行、当前行或下一行。
例如
// 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
运行 swiftlint rules
打印所有可用的规则及其标识符列表。
配置
通过在将运行 SwiftLint 的目录中添加一个 .swiftlint.yml
文件来配置 SwiftLint。以下参数可以进行配置
规则包含
disabled_rules
:从默认启用的规则集中禁用规则。opt_in_rules
:启用默认规则集之外的规则。only_rules
:只有在此列表中指定的规则会被启用。不能与disabled_rules
或opt_in_rules
一起指定。analyzer_rules
:这是一个完全独立的规则列表,仅由analyze
命令执行。所有分析规则都是可选的,因此这是唯一可配置的规则列表,没有对应disabled_rules
和only_rules
。
# By default, SwiftLint uses a set of sensible default rules you can adjust:
disabled_rules: # rule identifiers turned on by default to exclude from running
- colon
- comma
- control_statement
opt_in_rules: # some rules are turned off by default, so you need to opt-in
- empty_count # Find all the available rules by running: `swiftlint rules`
# Alternatively, specify all rules explicitly by uncommenting this option:
# only_rules: # delete `disabled_rules` & `opt_in_rules` if using this
# - empty_parameters
# - vertical_whitespace
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
- Source/*/ExcludedFile.swift # Exclude files with a wildcard
analyzer_rules: # Rules run by `swiftlint analyze` (experimental)
- explicit_self
# 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
allowed_symbols: ["_"] # these are allowed in type names
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, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging)
您还可以在配置文件中使用环境变量,通过在字符串中使用${SOME_VARIABLE}
来实现。
定义自定义规则
您可以使用以下语法在配置文件中定义基于正则表达式的自定义规则
custom_rules:
pirates_beat_ninjas: # rule identifier
included: ".*\\.swift" # regex that defines paths to include during linting. optional.
excluded: ".*Test\\.swift" # regex that defines paths to exclude during linting. optional
name: "Pirates Beat Ninjas" # rule name. optional.
regex: "([nN]inja)" # matching pattern
capture_group: 0 # number of regex capture group to highlight the rule violation at. optional.
match_kinds: # SyntaxKinds to match. optional.
- comment
- identifier
message: "Pirates are better than ninjas." # violation message. optional.
severity: error # violation severity. optional.
no_hiding_in_strings:
regex: "([nN]inja)"
match_kinds: string
输出结果将如下所示
您可以通过提供一个或多个match_kinds
来过滤匹配结果,这将拒绝包含不在此列表中的语法类型的匹配。以下所有可能的语法类型
- 参数
- builtin属性
- id属性
- id.buildconfig
- keyword.buildconfig
- 注释
- 标记注释
- URL注释
- doc注释
- 字段doc注释
- 标识符
- 关键字
- 数字
- 对象字面量
- 参数
- 占位符
- 字符串
- 字符串插值锚点
- 类型标识符
如果将自定义规则与only_rules
结合使用,请确保在only_rules
下添加custom_rules
项。
自动修复
SwiftLint可以自动纠正某些违规行为。磁盘上的文件将用修复后的版本覆盖。
请在运行swiftlint --fix
之前确认这些文件的备份,否则可能丢失重要数据。
由于在应用修复时,有可能修改文件导致违规(或其位移)被错误地更改,因此在纠正过程中禁用了标准lint检查。
分析(实验性)
实验性的analyze命令可以借助完整的类型检查AST来对Swift文件进行lint检查。必须通过--compiler-log-path
标志将包含清洁的swiftc
构建命令调用的编译器日志路径传递给analyze
,例如--compiler-log-path /path/to/xcodebuild.log
。
这可以通过以下方式获得
- 清理DerivedData(analyze不支持增量构建)
- 运行
xcodebuild -workspace {WORKSPACE}.xcworkspace -scheme {SCHEME} > xcodebuild.log
- 运行
swiftlint analyze --compiler-log-path xcodebuild.log
在此功能被标记为实验性的期间,该命令和相关SwiftLint代码可能随时会做出重大更改。分析规则通常也比lint规则慢得多。
使用多个配置文件
SwiftLint 提供了多种包含多个配置文件的方式。多个配置文件将合并为一个单独的配置文件,然后像单个配置文件一样应用。
有许多使用多个配置文件可能很有用的场景
例如,可以使用团队共享的 SwiftLint 配置文件,同时通过子配置文件允许在每个项目中覆盖。
团队配置
disabled_rules:
- force_cast
项目特定配置
opt_in_rules:
- force_cast
子/父配置(本地)
您可以在配置文件中指定 child_config
和/或 parent_config
的引用。这些引用应该是相对于配置文件指定文件夹的相对路径。这甚至适用于递归,只要没有循环和歧义。
子配置被视为一种改进,因此具有更高的优先级,而父配置在冲突情况下被视为基础,具有较低的优先级。
以下是一个示例,假设您有以下文件结构
ProjectRoot
|_ .swiftlint.yml
|_ .swiftlint_refinement.yml
|_ Base
|_ .swiftlint_base.yml
要包含改进和基础文件,您的 .swiftlint.yml
应该看起来像这样
child_config: .swiftlint_refinement.yml
parent_config: Base/.swiftlint_base.yml
在合并父和子配置时,会仔细处理 included
和 excluded
配置,以考虑到包含配置文件的目录位置差异。
子/父配置(远程)
就像您可以提供本地的 child_config
/ parent_config
引用一样,您也可以只放置指向配置文件的网址。为了让 SwiftLint 识别这些远程引用,它们必须以 http://
或 https://
开头。
引用的远程配置文件甚至可以递归引用其他远程配置文件,但不允许包括本地引用。
使用远程引用,您的 .swiftlint.yml
可以这样看起来
parent_config: https://myteamserver.com/our-base-swiftlint-config.yml
每次您运行 SwiftLint 并且有互联网连接时,SwiftLint 都会尝试获取所有引用的远程配置的最新版本。如果此请求超时,如果可用,则使用缓存的版本。如果没有可用的缓存版本,SwiftLint 会失败 – 但不用担心,一旦 SwiftLint 成功运行一次,就应有缓存版本。
如果需要,可以通过配置文件手动指定远程配置检索的超时时间,使用 remote_timeout
/ remote_timeout_if_cached
规范。默认值为 2 / 1 秒。
命令行
在通过命令行运行 SwiftLint 时,不仅可以提供一个配置文件,还可以传递一个层次结构,其中第一个配置被视为父配置,而最后一个配置被视为最高优先级的子配置。
包括两个配置文件的一个简单示例如下所示
swiftlint --config .swiftlint.yml --config .swiftlint_child.yml
嵌套配置
除了主配置(根目录下的 .swiftlint.yml
文件)之外,还可以将其他名为 .swiftlint.yml
的配置文件放入目录结构中,然后将其作为子配置合并,但仅对与配置在同一目录或更深目录中没有其他配置文件的同级目录中的文件有效。换句话说:嵌套配置不递归,每个文件除了主配置外,只能应用一个嵌套配置。
只有那些尚未用于构建主配置的 .swiftlint.yml
文件才被认为是嵌套配置(例如,通过以下方式引用: child_config: Folder/.swiftlint.yml
)。此外,忽略嵌套配置的 parent_config
/ child_config
指定,因为没有意义。
如果通过 --config
参数明确指定了(一个或多个)SwiftLint文件,则该配置将被视为一个覆盖项,无论目录中是否存在其他 .swiftlint.yml
文件。因此,如果要使用嵌套配置,请勿使用 --config
参数。
许可证
关于
SwiftLint 由 Realm Inc. 维护和资助。 Realm 的名称和标志是 Realm Inc. 的商标。
我们
感谢MacStadium为我们提供Mac Mini来运行我们的性能测试。