diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-14 18:09:44 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-14 18:09:44 +0300 |
commit | 874ead9c3a50de4c4ca4551eaf5b7eb976d26b50 (patch) | |
tree | 637ee9f2da5e251bc08ebf3e972209d51966bf7c /rubocop/cop | |
parent | 2e4c4055181eec9186458dd5dd3219c937032ec7 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'rubocop/cop')
-rw-r--r-- | rubocop/cop/performance/ar_count_each.rb | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/rubocop/cop/performance/ar_count_each.rb b/rubocop/cop/performance/ar_count_each.rb new file mode 100644 index 00000000000..2fe8e549872 --- /dev/null +++ b/rubocop/cop/performance/ar_count_each.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + class ARCountEach < RuboCop::Cop::Cop + def message(ivar) + "If #{ivar} is AR relation, avoid `#{ivar}.count ...; #{ivar}.each... `, this will trigger two queries. " \ + "Use `#{ivar}.load.size ...; #{ivar}.each... ` instead. If #{ivar} is an array, try to use #{ivar}.size." + end + + def_node_matcher :count_match, <<~PATTERN + (send (ivar $_) :count) + PATTERN + + def_node_matcher :each_match, <<~PATTERN + (send (ivar $_) :each) + PATTERN + + def file_name(node) + node.location.expression.source_buffer.name + end + + def in_haml_file?(node) + file_name(node).end_with?('.haml.rb') + end + + def on_send(node) + return unless in_haml_file?(node) + + ivar_count = count_match(node) + return unless ivar_count + + node.each_ancestor(:begin) do |begin_node| + begin_node.each_descendant do |n| + ivar_each = each_match(n) + + add_offense(node, location: :expression, message: message(ivar_count)) if ivar_each == ivar_count + end + end + end + end + end + end +end |