summaryrefslogtreecommitdiff
path: root/rubocop
diff options
context:
space:
mode:
Diffstat (limited to 'rubocop')
-rw-r--r--rubocop/cop/gitlab/predicate_memoization.rb39
-rw-r--r--rubocop/rubocop.rb1
2 files changed, 40 insertions, 0 deletions
diff --git a/rubocop/cop/gitlab/predicate_memoization.rb b/rubocop/cop/gitlab/predicate_memoization.rb
new file mode 100644
index 00000000000..3c25d61d087
--- /dev/null
+++ b/rubocop/cop/gitlab/predicate_memoization.rb
@@ -0,0 +1,39 @@
+module RuboCop
+ module Cop
+ module Gitlab
+ class PredicateMemoization < RuboCop::Cop::Cop
+ MSG = <<~EOL.freeze
+ Avoid using `@value ||= query` inside predicate methods in order to
+ properly memoize `false` or `nil` values.
+ https://docs.gitlab.com/ee/development/utilities.html#strongmemoize
+ EOL
+
+ def on_def(node)
+ return unless predicate_method?(node)
+
+ select_offenses(node).each do |offense|
+ add_offense(offense, location: :expression)
+ end
+ end
+
+ private
+
+ def predicate_method?(node)
+ node.method_name.to_s.end_with?('?')
+ end
+
+ def or_ivar_assignment?(or_assignment)
+ lhs = or_assignment.each_child_node.first
+
+ lhs.ivasgn_type?
+ end
+
+ def select_offenses(node)
+ node.each_descendant(:or_asgn).select do |or_assignment|
+ or_ivar_assignment?(or_assignment)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index 57af87f7fb9..9110237c538 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -1,4 +1,5 @@
require_relative 'cop/gitlab/module_with_instance_variables'
+require_relative 'cop/gitlab/predicate_memoization'
require_relative 'cop/include_sidekiq_worker'
require_relative 'cop/line_break_around_conditional_block'
require_relative 'cop/migration/add_column'