检测丢失的 sub!、sort!、map! 等
Detecting a missing sub!, sort!, map!, etc
在长期使用另一种语言编码 return 到 Ruby 之后,我经常假设 foo.sort
、foo.map {...}
、foo.sub /bar/, 'zip'
将 改变 foo。当然,我的意思是 foo.sort!
,等等。但在我注意到之前通常需要 3 或 4 次调试。同时,计算了排序,但没有分配给任何东西。我可以让 ruby 警告丢失的左值,就像 C 编译器警告函数被忽略的 return 值一样吗?
你是说 Perl 有点臭名昭著 "using map
in void context"?我不知道 Ruby 有这样的事情。听起来你需要更多的单元测试来发现这样的错误,然后它们才能深入到你的代码中,以至于被认为是错误。
请记住 Ruby 比 Perl 等语言灵活得多。例如,以下代码 可能 有用:
def rewrite(list)
list.map do |row|
row += '!'
end
end
从技术上讲,这是空上下文中的 map
,但因为它用作 return 值,所以 可能 在其他地方捕获。调用者有责任使用它。将方法本身标记为某种警告是大多数 linting 类型工具可以执行的级别。
这是一个非常的基本解析器:
@forgetful_methods = %w(sort map sub)
Dir['*.rb'].each do |script|
File.readlines(script).each.with_index(1) do |line, i|
@forgetful_methods.each do |method|
if line =~ /\.#{method}(?!!)/ && $` !~ /(=|\b(puts|print|return)\b|^#)/
puts format('%-25s (%3d) : %s', script, i, line.strip)
end
end
end
end
# =>
# brace_globbing.rb ( 13) : subpatterns.map{|subpattern| explode_extglob(match.pre_match+subpattern+match.post_match)}.flatten
# delegate.rb ( 11) : @targets.map { |t| t.send(m, *args) }
它检查当前目录中的每个 ruby 脚本是否有 sort
、map
或 sub
没有 !
且前面没有 =
、puts
、print
或 return
.
这只是一个开始,但也许它可以帮助您找到一些唾手可得的成果。
但是,有很多误报。
更复杂的版本可以使用抽象语法树,例如 Ripper。
在长期使用另一种语言编码 return 到 Ruby 之后,我经常假设 foo.sort
、foo.map {...}
、foo.sub /bar/, 'zip'
将 改变 foo。当然,我的意思是 foo.sort!
,等等。但在我注意到之前通常需要 3 或 4 次调试。同时,计算了排序,但没有分配给任何东西。我可以让 ruby 警告丢失的左值,就像 C 编译器警告函数被忽略的 return 值一样吗?
你是说 Perl 有点臭名昭著 "using map
in void context"?我不知道 Ruby 有这样的事情。听起来你需要更多的单元测试来发现这样的错误,然后它们才能深入到你的代码中,以至于被认为是错误。
请记住 Ruby 比 Perl 等语言灵活得多。例如,以下代码 可能 有用:
def rewrite(list)
list.map do |row|
row += '!'
end
end
从技术上讲,这是空上下文中的 map
,但因为它用作 return 值,所以 可能 在其他地方捕获。调用者有责任使用它。将方法本身标记为某种警告是大多数 linting 类型工具可以执行的级别。
这是一个非常的基本解析器:
@forgetful_methods = %w(sort map sub)
Dir['*.rb'].each do |script|
File.readlines(script).each.with_index(1) do |line, i|
@forgetful_methods.each do |method|
if line =~ /\.#{method}(?!!)/ && $` !~ /(=|\b(puts|print|return)\b|^#)/
puts format('%-25s (%3d) : %s', script, i, line.strip)
end
end
end
end
# =>
# brace_globbing.rb ( 13) : subpatterns.map{|subpattern| explode_extglob(match.pre_match+subpattern+match.post_match)}.flatten
# delegate.rb ( 11) : @targets.map { |t| t.send(m, *args) }
它检查当前目录中的每个 ruby 脚本是否有 sort
、map
或 sub
没有 !
且前面没有 =
、puts
、print
或 return
.
这只是一个开始,但也许它可以帮助您找到一些唾手可得的成果。 但是,有很多误报。
更复杂的版本可以使用抽象语法树,例如 Ripper。