v1 升级说明
Cop 升级指南
您的自定义 cop 应该继续在 v1 中工作。
但是,建议您按照以下步骤调整它们以使用 v1 API
1) 您的类应该继承自 RuboCop::Cop::Base
而不是 RuboCop::Cop::Cop
。
2) 找到您对 add_offense
的调用,并确保您将 AST::Node
、::Parser::Source::Comment
或 ::Parser::Source::Range
作为第一个参数传递,并且没有 location:
命名参数。
示例
# Before
class MySillyCop < Cop
def on_send(node)
if node.method_name == :-
add_offense(node, location: :selector, message: "Be positive")
end
end
end
# After
class MySillyCop < Base
def on_send(node)
if node.method_name == :-
add_offense(node.loc.selector, message: "Be positive")
end
end
end
如果您的类支持自动更正
您的类必须 extend AutoCorrector
。
corrector
现在从 add_offense
中产生。将您方法 autocorrect
的代码移动到该块中,并且不要将您的更正包装在 lambda 中。Corrector
更强大,现在可以 merge
。
示例
# Before
class MySillyCorrectingCop < Cop
def on_send(node)
if node.method_name == :-
add_offense(node, location: :selector, message: 'Be positive')
end
end
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.loc.selector, '+')
end
end
end
# After
class MySillyCorrectingCop < Base
extend AutoCorrector
def on_send(node)
if node.method_name == :-
add_offense(node.loc.selector, message: 'Be positive') do |corrector|
corrector.replace(node.loc.selector, '+')
end
end
end
end
实例变量
不要使用 RuboCop 的内部实例变量。如果您使用的是 @processed_source
,请使用 processed_source
。如果您需要访问实例变量,请打开一个包含您的用例的 issue。
默认情况下,对于给定的 processed_source
,Cop 实例只会调用一次,因此在调查开始时实例变量将未初始化。使用 @cache ||= …
就可以了。如果你想初始化一些实例变量,回调 on_new_investigation
是最好的地方。
class MyCachingCop < Base
def on_send(node)
if my_cached_data[node]
@counts(node.method_name) += 1
#...
end
end
# One way:
def my_cached_data
@data ||= processed_source.comments.map { # ... }
end
# Another way:
def on_new_investigation
@counts = Hash.new(0)
super # Be nice and call super for callback
end
end
其他 API 更改
如果你的 Cop 使用 investigate
、investigate_post_walk
、join_force?
或内部类,例如 Corrector
、Commissioner
、Team
,这些都已更改。请参阅 详细的 API 更改。
升级规范
强烈建议你在规范中使用 expect_offense
/ expect_correction
/ expect_no_offense
,例如:
require 'rubocop/rspec/support'
RSpec.describe RuboCop::Cop::Custom::MySillyCorrectingCop, :config do
# No need for `let(:cop)`
it 'is positive' do
expect_offense(<<~RUBY)
42 + 2 - 2
^ Be positive
RUBY
expect_correction(<<~RUBY)
42 + 2 + 2
RUBY
end
it 'does not register an offense for calls to `despair`' do
expect_no_offenses(<<~RUBY)
"don't".despair
RUBY
end
end
在极少数情况下,如果你直接使用类 RuboCop::Cop::Corrector
,它已经改变了一些,但你可以使用 RuboCop::Cop::Legacy::Corrector
来简化你的过渡,它旨在与旧版本兼容。你需要 require 'rubocop/cop/legacy/corrector'
。
详细的 API 更改
本节列出了 API 的所有更改(无论大小)。它适用于 RuboCop 的维护者;大多数 Cop 作者不会受到这些更改的影响,因此不是目标受众。
基类
旧版本:Cop 继承自 Cop::Cop
。
当前:Cop 继承自 Cop::Base
。拥有不同的基类使实现更加干净,并可以轻松地指示正在使用哪个 API。Cop::Cop
继承自 Cop::Base
并细化了一些方法以实现向后兼容性。
add_offense
API
参数
旧版本:接口允许使用 node
,并带有可选的 location
(符号或范围)或带有强制范围的范围作为位置。一些 Cop 滥用了 node
参数并传递了非常不同的内容。
当前:传递一个范围(或作为 node.loc.expression
的快捷方式的节点),没有 location:
。不允许滥用。
自动修正
#autocorrect
遗留: 调用 autocorrect
,除非它被禁用或自动修正被关闭。
当前: yield 一个修正器,除非它被禁用。如果自动修正被关闭等,修正器将被忽略。不支持 autocorrect
方法,但如果该方法仍然定义,会发出警告。
异常处理
两者:Commissioner
会在分析过程中(除非 option[:raise_error]
)捕获所有 StandardError
,并在其错误列表中存储相应的 ErrorWithAnalyzedFileLocation
。这在调用 cop 的 on_send
& al. 或调用 investigate
/ investigate_post_walk
回调时完成。
遗留: 自动修正 cop 对错误的处理方式不同,具体取决于错误发生的时间。一些错误被静默忽略。其他错误被捕获如上。其他错误导致崩溃。Team
中的一些代码会捕获错误并将它们添加到错误列表中,但我认为代码不起作用。
当前: Team
不再有任何特殊的错误处理,因为潜在的异常发生在 Commissioner
运行时。
其他错误处理
遗留: 覆盖错误被静默忽略。调用 insert_before
时,范围超出源代码范围会被静默修复。
当前: 不会忽略此类错误。虽然允许一个 Cop 的修正覆盖另一个 Cop 的修正,但任何给定的 Cop 不应该发出相互覆盖的修正,或者具有无效范围的修正,否则这些修正将被列在处理错误中。
内部类
其他 API 更改
-
澄清了 Commissioner 的内部 API。它调用
begin_investigation
并接收complete_investigation
中的结果。 -
新方法
add_global_offense
用于不附加到特定位置的违规行为;目前仅用于语法错误。 -
#offenses
:不再可访问。 -
回调
investigate(processed_source)
和investigate_post_walk(processed_source)
被重命名为on_new_investigation
和on_investigation_end
,并且不接受参数;所有on_
回调都应该依赖于processed_source
。 -
#find_location
已弃用。 -
Correction
已弃用。 -
一些注册表访问方法已从
Cop
移动到Registry
,既是为了正确性(例如,MyCop.qualified_cop_name
不起作用,也没有意义),也是为了让Cop::Cop
不再包含任何必要的代码。保持向后兼容性。-
Cop.registry
=>Registry.global
-
Cop.all
=>Registry.all
-
Cop.qualified_cop_name
=>Registry.qualified_cop_name
-
-
用于跟踪配置选项的排除限制的
ConfigurableMax
混合已弃用。请改用exclude_limit ParameterName
。