summaryrefslogtreecommitdiff
path: root/rubocop
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-14 15:09:44 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-14 15:09:44 +0000
commit874ead9c3a50de4c4ca4551eaf5b7eb976d26b50 (patch)
tree637ee9f2da5e251bc08ebf3e972209d51966bf7c /rubocop
parent2e4c4055181eec9186458dd5dd3219c937032ec7 (diff)
downloadgitlab-ce-874ead9c3a50de4c4ca4551eaf5b7eb976d26b50.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'rubocop')
-rw-r--r--rubocop/cop/performance/ar_count_each.rb45
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