51 lines
1.3 KiB
Crystal
51 lines
1.3 KiB
Crystal
require "./base"
|
|
|
|
module Ameba::Rule::Performance
|
|
# This rule is used to identify usage of arg-less `Enumerable#any?` calls.
|
|
#
|
|
# Using `Enumerable#any?` instead of `Enumerable#empty?` might lead to an
|
|
# unexpected results (like `[nil, false].any? # => false`). In some cases
|
|
# it also might be less efficient, since it iterates until the block will
|
|
# return a _truthy_ value, instead of just checking if there's at least
|
|
# one value present.
|
|
#
|
|
# For example, this is considered invalid:
|
|
#
|
|
# ```
|
|
# [1, 2, 3].any?
|
|
# ```
|
|
#
|
|
# And it should be written as this:
|
|
#
|
|
# ```
|
|
# ![1, 2, 3].empty?
|
|
# ```
|
|
#
|
|
# YAML configuration example:
|
|
#
|
|
# ```
|
|
# Performance/AnyInsteadOfEmpty:
|
|
# Enabled: true
|
|
# ```
|
|
class AnyInsteadOfEmpty < Base
|
|
include AST::Util
|
|
|
|
properties do
|
|
description "Identifies usage of arg-less `any?` calls"
|
|
end
|
|
|
|
MSG = "Use `!{...}.empty?` instead of `{...}.any?`"
|
|
|
|
def test(source, node : Crystal::Call)
|
|
return unless node.name == "any?"
|
|
return unless node.block.nil? && node.args.empty?
|
|
return unless node.obj
|
|
|
|
return unless name_location = node.name_location
|
|
return unless end_location = name_end_location(node)
|
|
|
|
issue_for name_location, end_location, MSG
|
|
end
|
|
end
|
|
end
|