配置
RuboCop 的行为可以通过 .rubocop.yml 配置文件进行控制。它可以启用/禁用某些 cop(检查)并更改其行为(如果它们接受任何参数)。该文件可以放在您的主目录、XDG 配置目录或某个项目目录中。
该文件具有以下格式
inherit_from: ../.rubocop.yml
Style/Encoding:
Enabled: false
Layout/LineLength:
Max: 99
建议使用限定 cop 名称及其类型,例如 Style ,但只要 cop 名称在所有类型中都是唯一的,则不是必需的。
|
配置文件位置
RuboCop 将从检查文件的目录开始查找配置文件,并一直向上查找,直到根目录。
如果在到达项目根目录之前仍未找到,则将在 .config directory of the project root 和用户的全局配置位置中搜索。用户的全局配置位置包括项目根目录的点文件或配置文件,以及 XDG Base Directory specification 中的配置文件。
-
项目根目录下的
.config/.rubocop.yml
或.config/rubocop/config.yml
-
~/.rubocop.yml
-
$XDG_CONFIG_HOME/rubocop/config.yml
(如果未设置$XDG_CONFIG_HOME
,则扩展为~/.config/rubocop/config.yml
)
如果两个文件都存在,则将选择点文件。
例如,如果从 /path/to/project/lib/utils
内部调用 RuboCop,则 RuboCop 将使用以下文件中第一个指定的配置
-
/path/to/project/lib/utils/.rubocop.yml
-
/path/to/project/lib/.rubocop.yml
-
/path/to/project/.rubocop.yml
-
/path/to/project/.config/.rubocop.yml
-
/path/to/project/.config/rubocop/config.yml
-
/.rubocop.yml
-
~/.rubocop.yml
-
~/.config/rubocop/config.yml
如果通过 --config 标志在命令行中传递了特定配置文件,则所有先前的逻辑都不适用。在这种情况下,解析的配置文件将是传递给 CLI 的配置文件。
|
继承
所有配置都继承自 RuboCop 的默认配置(参见“默认值”)。
RuboCop 还支持用户配置文件中的继承。最常见的示例是 .rubocop_todo.yml
文件(参见下面的“自动生成的配置”)。
子文件(继承文件)中的设置会覆盖父文件(被继承文件)中的设置,但以下情况除外。
哈希继承与其他类型
作为哈希的配置参数,例如 Style/CollectionMethods
中的 PreferredMethods
,会与父配置中的相同参数合并。这意味着子配置中给出的任何键值对都会覆盖父配置中的相同键。使用 ~
(YAML 中的 nil
表示)作为值会取消父配置中对应键的设置。例如
Style/CollectionMethods:
Enabled: true
PreferredMethods:
# No preference for collect, keep all others from default config.
collect: ~
其他类型,例如 AllCops
/ Include
(数组),会被子设置覆盖。
数组覆盖是因为如果它们被合并,将无法在子文件中删除元素。
但是,高级用户仍然可以使用 inherit_mode
设置合并数组。请参阅下面的“使用 inherit_mode 合并数组”。
从项目中的另一个配置文件继承
可选的 inherit_from
指令用于包含来自一个或多个文件中的配置。这使得将项目的通用设置放在项目根目录下的 .rubocop.yml
文件中成为可能,然后在子目录中只设置与这些规则的偏差。这些文件可以使用绝对路径或相对于引用它们的文件的路径给出。inherit_from
指令之后的设置会覆盖从继承的文件中继承的任何设置。当包含多个文件时,列表中的第一个文件具有最低优先级,最后一个文件具有最高优先级。多个继承的格式为
inherit_from:
- ../.rubocop.yml
- ../conf/.rubocop.yml
inherit_from
也接受通配符,例如
inherit_from:
- packages/*/.rubocop_todo.yml
上面的例子是一个潜在的用例:允许仓库中的组件组织自己的 .rubocop_todo.yml
文件。
从远程 URL 继承配置
可选的 inherit_from
指令可以包含指向远程文件的完整 URL。这使得将项目的通用设置存储在 HTTP 服务器上并在多个项目之间共享成为可能。
远程配置文件会缓存在本地,并且只有在以下情况下才会更新:
-
文件不存在。
-
文件在过去 24 小时内没有更新。
-
远程副本的修改时间比本地副本更新。
您可以在同一个配置文件中从远程和本地文件继承,并且相同的继承规则适用于远程 URL 和从本地文件继承,其中列表中的第一个文件具有最低优先级,最后一个文件具有最高优先级。使用 URL 的多个继承的格式为
inherit_from:
- http://www.example.com/rubocop.yml
- ../.rubocop.yml
您可以从具有基本身份验证的仓库继承,该身份验证被授权访问仓库,如下所示
inherit_from:
- http://<user_name>:<password>@raw.github.com/example/rubocop.yml
一个 GitHub 个人访问令牌 也可以按如下方式配置
inherit_from:
- http://<personal_access_token>@raw.github.com/example/rubocop.yml
从依赖 gem 继承配置
可选的 inherit_gem
指令用于包含来自当前项目外部的一个或多个 gem 的配置。这使得从多个不同的项目中继承共享依赖项的 RuboCop 配置成为可能。
以这种方式继承的配置将基本上被预先附加到 inherit_from
指令,这样 inherit_gem
配置将首先加载,然后 inherit_from
相对文件路径将被加载(覆盖来自 gem 的配置),最后配置 文件中的其余指令将覆盖任何继承的配置。这意味着从一个或多个 gem 继承的配置具有最低的继承优先级。
该指令应使用 gem 名称作为键,gem 内的相对路径作为值,格式化为 YAML 哈希。
inherit_gem:
my-shared-gem: .rubocop.yml
cucumber: conf/rubocop.yml
数组也可以用作值,以包含来自单个 gem 的多个配置文件。
inherit_gem:
my-shared-gem:
- default.yml
- strict.yml
如果共享依赖项使用 Bundler Gemfile 声明,并且 gem 使用 bundle install 安装,则需要使用 Bundler 调用 RuboCop,以便在运行时找到依赖项的安装路径。
|
$ bundle exec rubocop <options...>
使用 inherit_mode 合并数组
可选的指令 inherit_mode
指定具有数组值的哪些配置键应合并在一起,而不是覆盖继承的值。
这适用于使用 inherit_from
的显式继承,以及来自 默认配置 的隐式继承。
给定以下配置
# .rubocop.yml
inherit_from:
- shared.yml
inherit_mode:
merge:
- Exclude
AllCops:
Exclude:
- 'generated/**/*.rb'
Style/For:
Exclude:
- bar.rb
# .shared.yml
Style/For:
Exclude:
- foo.rb
此示例中 Style/For
规则的 Exclude
列表将是 ['foo.rb', 'bar.rb']
。类似地,AllCops:Exclude
列表将包含所有默认模式以及本地添加的 generated/**/*.rb
条目。
该指令也可以用于单个规则配置,以覆盖全局设置。
inherit_from:
- shared.yml
inherit_mode:
merge:
- Exclude
Style/For:
inherit_mode:
override:
- Exclude
Exclude:
- bar.rb
在此示例中,Exclude
将仅包含 bar.rb
。
预处理
配置文件使用 ERB 模板机制进行预处理。这使得添加动态内容成为可能,这些内容将在读取配置文件时进行评估。例如,您可以让 RuboCop 忽略 Git 忽略的所有文件。
AllCops:
Exclude:
<% `git status --ignored --porcelain`.lines.grep(/^!! /).each do |path| %>
- <%= path.sub(/^!! /, '').sub(/\/$/, '/**/*') %>
<% end %>
默认值
RuboCop 主目录下的文件 config/default.yml 包含所有配置继承的默认设置。项目和个人 .rubocop.yml
文件只需要设置与默认设置不同的设置。如果项目、主目录或 XDG 目录中没有 .rubocop.yml
文件,则将使用 config/default.yml
。
包含/排除文件
RuboCop 从运行目录或命令行参数中给定的目录开始进行递归文件搜索。匹配 AllCops
/Include
下列出的任何模式的文件,以及包含 AllCops
/RubyInterpreters
下列出的已知 Ruby 解释器之一的哈希邦 (#!
) 声明的无扩展名文件,都会被检查,除非该文件也匹配 AllCops
/Exclude
中的模式。默认情况下,不会搜索隐藏目录(即名称以点开头的目录)。
以下是一个可能用于 Rails 项目的示例
AllCops:
Exclude:
- 'db/**/*'
- 'config/**/*'
- 'script/**/*'
- 'bin/{rails,rake}'
- !ruby/regexp /old_and_unused\.rb$/
# other configuration
# ...
当检查作为 RuboCop 命令行参数给定的特定目录(或文件)时,也会检查 AllCops / Exclude 下列出的模式。如果您想在这种情况下应用 AllCops / Exclude 规则,请在命令行参数中添加 --force-exclusion 。
|
以下是一个示例
# .rubocop.yml
AllCops:
Exclude:
- foo.rb
如果 foo.rb
指定为 RuboCop 的命令行参数,则结果为
# RuboCop inspects foo.rb.
$ bundle exec rubocop foo.rb
# RuboCop does not inspect foo.rb.
$ bundle exec rubocop --force-exclusion foo.rb
路径相对性
在 .rubocop.yml
和任何其他以 .rubocop
开头的配置文件中,文件和目录相对于配置文件所在的目录指定。在不以 .rubocop
开头的配置文件中,例如 our_company_defaults.yml
,路径相对于运行 rubocop
的目录。
这会影响具有可自定义路径的 cop:如果默认值为 db/migrate/*.rb
,并且 cop 在 db/migrate/.rubocop.yml
中启用,则需要将路径显式设置为 *.rb
,因为默认情况下会查找 db/migrate/db/migrate/*.rb
。这可能不是您想要的。
默认情况下不会包含的异常文件
RuboCop 带有常见 Ruby 文件名和扩展名的综合列表。但是,如果您希望 RuboCop 检查默认情况下未包含的文件,则需要在命令行中传递它们,或在 AllCops
/Include
下添加它们的条目。请记住,您的配置文件会覆盖 RuboCops 的默认值。在以下示例中,我们希望包含 foo.unusual_extension
,但我们也必须从被覆盖的 default.yml
中复制任何其他需要的模式。
AllCops:
Include:
- foo.unusual_extension
- '**/*.rb'
- '**/*.gemfile'
- '**/*.gemspec'
- '**/*.rake'
- '**/*.ru'
- '**/Gemfile'
- '**/Rakefile'
已弃用的模式
仅为文件名(例如 Rakefile
)的模式将匹配任何目录中的该文件名,但此模式样式已弃用。在任何目录(包括当前目录)中匹配该文件的正确方法是 **/Rakefile
。
模式 config/**
将匹配 config
下的任何文件(递归),但此模式样式已弃用,应替换为 config/**/*
。
特定于 Cop 的 Include
和 Exclude
当需要时,Cop 只能在特定文件集上运行(例如,您可能希望仅在路径匹配 app/models/*.rb
的文件上运行一些 Rails 模型检查)。所有 Cop 都支持 Include
参数。
Rails/HasAndBelongsToMany:
Include:
- app/models/*.rb
当需要时,Cop 也可以仅排除特定文件集(例如,您可能希望仅在特定文件上运行某些 Cop)。所有 Cop 都支持 Exclude
参数。
Rails/HasAndBelongsToMany:
Exclude:
- app/models/problematic.rb
通用配置参数
除了 Include
和 Exclude
之外,以下参数可用于每个 Cop。
Enabled
可以通过将特定 Cop 的 Enabled
设置为 false
来禁用特定 Cop。
Layout/LineLength:
Enabled: false
大多数 Cop 默认情况下是启用的。在主要版本之间引入或显着更新的 Cop 处于特殊的待处理状态(在 "版本控制" 中了解更多信息)。一些 Cop 在 config/default.yml 中配置了上述 Enabled: false
,默认情况下是禁用的。
可以通过将 DisabledByDefault
或 EnabledByDefault
(但不能同时设置两者)设置为 true
来更改 Cop 启用过程。这些设置会覆盖所有 Cop 的默认值,使其禁用或启用,除了 Lint/Syntax
,它始终启用,无论 Cop 的默认值(启用、禁用或待处理)如何。
AllCops:
DisabledByDefault: true
除了 `Lint/Syntax` 之外的所有 cops 默认情况下都是禁用的。只有在用户配置文件中出现 `Enabled: true` 的 cops 才会被启用;其他所有 cops 都会被禁用,而无需在配置中显式禁用它们。也可以通过添加例如以下内容来启用整个部门。
Style:
Enabled: true
然后,`Style` 部门中的所有 cops 都被启用。
如果一个部门被禁用,该部门中的 cops 仍然可以被单独启用,并且该设置会覆盖同一配置文件和任何继承文件中该部门的设置。
inherit_from: config_that_disables_the_metrics_department.yml
Metrics/MethodLength:
Enabled: true
Style:
Enabled: false
Style/Alias:
Enabled: true
严重性
每个 cop 都有一个默认的严重性级别,该级别取决于它所属的部门。对于 `Lint`,级别通常为 `warning`,对于其他所有级别,级别通常为 `convention`,但这可以在用户配置中更改。Cops 可以自定义它们的严重性级别。允许的值为 `info`、`refactor`、`convention`、`warning`、`error` 和 `fatal`。
严重性为 `info` 的 cops 将被报告,但不会导致 `rubocop` 返回非零值。
上述一般规则有一个例外,那就是 `Lint/Syntax`,这是一个特殊的 cop,它在调用其他 cops 之前检查语法错误。它不能被禁用,并且它的严重性(`fatal`)不能在配置中更改。
Lint:
Severity: error
Metrics/CyclomaticComplexity:
Severity: warning
详情
单个 cops 可以用额外的细节来修饰违规消息。
Layout/LineLength:
Details: >-
If lines are too short, text becomes hard to read because you must
constantly jump from one line to the next while reading. If lines are too
long, the line jumping becomes too hard because you "lose the line" while
going back to the start of the next line. 80 characters is a good
compromise.
这些细节只有在使用 `--extra-details` 标志运行 RuboCop 时,或者在全局 RuboCop 配置中将 `ExtraDetails` 设置为 true 时才会显示。
自动更正
支持 `--autocorrect` 选项的 cops 为自动更正提供了灵活的设置。这些设置可以在配置文件中指定,如下所示。
-
always
-
contextual
-
disabled
always (默认)
此设置默认情况下始终启用自动更正。为了向后兼容,`true` 与 `always` 的处理方式相同。
Style/PerlBackrefs:
AutoCorrect: always # or true
contextual
此设置在从 `rubocop` 命令启动时启用自动更正,但它不可通过 LSP 使用。例如,`rubocop --lsp`、`rubocop --editor-mode` 或已应用 `RuboCop::LSP.enable` 的程序。
通过命令行的检查被视为已完成的代码。
Style/PerlBackrefs:
AutoCorrect: contextual
此设置在编辑器中编辑期间阻止自动更正。例如,使用 `textDocument/formatting` LSP 方法。但是,由用户有意操作触发的 `workspace/executeCommand` LSP 方法会尊重用户对自动更正的意图。
此外,对于像 `Metrics` cops 这样的情况,其中突出显示范围扩展到类、模块、方法或块的整个主体,违规范围将仅限于名称。这种方法有助于避免在编辑器显示中出现冗余和嘈杂的违规。
设置目标 Ruby 版本
一些检查依赖于被检查代码必须运行的 Ruby 解释器的版本。例如,强制使用 Ruby 2.6+ 无限范围 foo[n..]
而不是 foo[n..-1]
可以帮助使您的代码更短、更一致……除非 它必须在例如 Ruby 2.5 上运行。
用户可以使用以下方法让 RuboCop 知道您的项目支持的最旧的 Ruby 版本
AllCops:
TargetRubyVersion: 2.5
当指定 ParserEngine: parser_prism 时,TargetRubyVersion 必须设置为 3.3 或更高。
|
如果您的配置中未指定 TargetRubyVersion
,则 RuboCop 将检查您的项目以查找可能已指定 Ruby 版本的一系列其他文件。将检查的文件(按此顺序)是:*.gemspec
、.ruby-version
、.tool-versions
和 Gemfile.lock
。
如果无法通过上述任何来源找到目标 Ruby 版本,则将使用默认目标 Ruby 版本。
在 *.gemspec
文件中查找目标 Ruby
为了让 RuboCop 解析 *.gemspec
文件的 required_ruby_version
,必须使用以下语法之一指定 Ruby 版本
-
字符串范围,例如
'~> 3.2.0'
或'>= 3.2.2'
-
字符串数组,例如
['>= 3.0.0', '< 3.4.0']
-
Gem::Requirement
,例如Gem::Requirement.new('>= 3.1.2')
如果 *.gemspec
文件通过任何这些方式指定了支持的 Ruby 版本范围,则将使用以下 Ruby 版本中的较大者
-
与您指定范围兼容的最低 Ruby 版本
-
您当前 RuboCop 版本支持的最低 Ruby 版本
如果一个 *.gemspec
文件动态定义了它的 required_ruby_version
(例如通过读取 .ruby-version
文件,通过环境变量,引用常量或局部变量等),那么 RuboCop 不会检测到该 Ruby 版本,而是会尝试在其他地方找到目标 Ruby 版本。
设置解析器引擎
解析器引擎配置在 RuboCop 1.62 中引入。这个实验性功能已经考虑了一段时间。 |
RuboCop 允许通过指定 parser_whitequark
或 parser_prism
作为 ParserEngine
的值来切换后端解析器。
以下是每个值使用的后端解析器
-
ParserEngine: parser_whitequark
… https://github.com/whitequark/parser -
ParserEngine: parser_prism
… https://github.com/ruby/prism (Prism::Translation::Parser
)
默认情况下,隐式使用 parser_whitequark
。
parser_whitequark
可以分析 Ruby 2.0 及以上版本的源代码
AllCops:
ParserEngine: parser_whitequark
parser_prism
可以分析 Ruby 3.3 及以上版本的源代码
AllCops:
ParserEngine: parser_prism
TargetRubyVersion: 3.3
parser_prism
的分析速度往往比 parser_whitequark
快。
由于对 Prism 的支持是实验性的,它不包含在 RuboCop 的运行时依赖项中。如果通过 Bundler 运行 RuboCop,请将 gem 'prism' 添加到您的 Gemfile 中
|
gem 'prism'
parser_prism
中存在一些与 parser_whitequark
不兼容的地方,这也是它被认为是实验性的主要原因。我们正在与 Prism 团队合作解决这些问题。您可以在 这里 跟踪影响 RuboCop 的 Prism 中已知问题。
自动生成的配置
如果您有一个代码库,其中存在大量的违规,那么使用 rubocop --auto-gen-config
是一个好主意,它会创建 .rubocop_todo.yml
并将 inherit_from: .rubocop_todo.yml
添加到您的 .rubocop.yml
中。生成的 .rubocop_todo.yml
文件包含配置,用于禁用当前检测到代码中违规的 cop,方法是更改 cop 的配置,排除违规文件,或者在达到文件数量限制后完全禁用 cop。
通过添加 --exclude-limit COUNT
选项,例如 rubocop --auto-gen-config --exclude-limit 5
,您可以更改在完全禁用 cop 之前要排除多少个文件。默认的 COUNT 为 15。如果您不希望 cop 无论有多少文件都完全禁用,请使用 --no-exclude-limit
选项,例如 rubocop --auto-gen-config --no-exclude-limit
。
下一步是将.rubocop_todo.yml
中的配置剪切并粘贴到.rubocop.yml
中,对于您认为符合您的(组织)代码风格且不适合待办事项列表的所有内容。请注意每个条目上面的注释。它们可以揭示配置参数,例如EnforcedStyle
,它可以用来修改 cop 的行为,而不是完全禁用它。
然后,您可以开始逐个删除生成的.rubocop_todo.yml
文件中的条目,因为您正在处理代码中的所有违规行为。您还可以使用相同的选项重新生成您的.rubocop_todo.yml
,方法是运行rubocop --regenerate-todo
。
除了配置之外,另一种抑制违规报告的方法是通过源代码注释。这些可以手动或自动添加。请参阅下面的“在源代码中禁用 Cops”。
Metrics
部门中的 cops 默认情况下将在.rubocop_todo.yml
中生成Max
参数。这些参数的值将足够高,以便在您下次运行rubocop
时不会报告任何违规行为。如果您希望排除文件(例如其他 cops),请在使用--auto-gen-config
运行时添加--auto-gen-only-exclude
。如果排除的文件数量超过排除限制,它仍然会更改最大值。
一些 cops 具有一个名为EnforcedStyle
的可配置选项。默认情况下,在生成.rubocop_todo.yml
时,如果所有文件都使用一种风格,这些 cops 将添加正在使用的风格的设置。如果您希望逐文件排除,请在使用--auto-gen-config
时添加--no-auto-gen-enforced-style
选项。
更新配置文件
当您更新 RuboCop 版本时,有时您需要更改.rubocop.yml
。如果您使用mry,您可以自动将.rubocop.yml
更新到最新版本。
$ gem install mry
# Update to latest version
$ mry .rubocop.yml
# Update to specified version
$ mry --target=0.48.0 .rubocop.yml
有关更多信息,请参阅https://github.com/pocke/mry。
在源代码中禁用 Cops
可以通过添加以下注释,在文件的某个部分本地禁用一个或多个单独的 cops
# rubocop:disable Layout/LineLength, Style/StringLiterals
[...]
# rubocop:enable Layout/LineLength, Style/StringLiterals
您也可以通过在注释中给出部门名称来禁用整个部门。
# rubocop:disable Metrics, Layout/LineLength
[...]
# rubocop:enable Metrics, Layout/LineLength
您也可以使用以下方法禁用所有 cop:
# rubocop:disable all
[...]
# rubocop:enable all
在您想要区分有意禁用的 cop 和您希望稍后重新审视的 cop 的情况下,您可以使用 rubocop:todo
作为 rubocop:disable
的别名。
# rubocop:todo Layout/LineLength, Style/StringLiterals
[...]
# rubocop:enable Layout/LineLength, Style/StringLiterals
可以使用行尾注释在一行中禁用一个或多个 cop。
for x in (0..19) # rubocop:disable Style/For
如果您想禁用检查注释的 cop,可以在注释行上添加“内部注释”。
# coding: utf-8 # rubocop:disable Style/Encoding
运行 rubocop --autocorrect --disable-uncorrectable
将创建注释以禁用所有无法自动更正的违规。
在禁用注释中不要写入除 cop 名称以外的任何内容。例如:
# rubocop:disable Layout/LineLength --This is a bad comment that includes other than cop name.
在源代码中临时启用 cop
与在源代码中禁用 cop 的方式类似,您也可以在需要对文件的一部分强制执行特定规则时临时启用特定 cop。
让我们使用 cop Style/AsciiComments
,它默认情况下为 Enabled: false
。如果您希望特定文件具有仅 ASCII 的注释以与某些特定后处理兼容。
# rubocop:enable Style/AsciiComments
# If applicable, leave a comment to others explaining the rationale:
# We need the comments to remain ASCII only for compatibility with lib/post_processor.rb
class Restaurant
# This comment has to be ASCII-only because of the rubocop:enable directive
def menu
return dishes.map(&:humanize)
end
end
您也可以通过在之后禁用 cop 来对文件的一部分强制执行相同的操作
class Dish
def humanize
return [
"Delicious #{self.name}"
*ingredients
].join("\n")
end
end
# rubocop:enable Style/AsciiComments
# If applicable, leave a comment to others explaining the rationale:
# We need the comments to remain ASCII only for compatibility with lib/post_processor.rb
class Restaurant
# This comment has to be ASCII-only because of the rubocop:enable directive
def menu
return dishes.map(&:humanize)
end
end
# rubocop:disable Style/AsciiComments
class Ingredient
# Notice how the comment below is non-ASCII
# Gets rid of odd characters like 😀,
def sanitize
self.name.gsub(/[^a-z]/, '')
end
end
设置样式指南 URL
您可以使用 StyleGuideBaseURL
指定样式指南的基 URL。如果在 AllCops
下指定,则所有 cop 都是目标。
AllCops:
StyleGuideBaseURL: https://ruby-style-guide.ruby-lang.org.cn
StyleGuideBaseURL
与指定给 cop 的 StyleGuide
相结合。
Lint/UselessAssignment:
StyleGuide: '#underscore-unused-vars'
如果在特定部门下指定,则优先于 AllCops
。以下是指定 Rails
部门的示例。
Rails:
StyleGuideBaseURL: https://rails-style-guide.ruby-lang.org.cn
Rails/TimeZone:
StyleGuide: '#time'
样式指南 URL 为 https://rails-style-guide.ruby-lang.org.cn#time。