summaryrefslogtreecommitdiff
path: root/rubocop/cop/gitlab/delegate_predicate_methods.rb
diff options
context:
space:
mode:
Diffstat (limited to 'rubocop/cop/gitlab/delegate_predicate_methods.rb')
-rw-r--r--rubocop/cop/gitlab/delegate_predicate_methods.rb45
1 files changed, 45 insertions, 0 deletions
diff --git a/rubocop/cop/gitlab/delegate_predicate_methods.rb b/rubocop/cop/gitlab/delegate_predicate_methods.rb
new file mode 100644
index 00000000000..43b5184faab
--- /dev/null
+++ b/rubocop/cop/gitlab/delegate_predicate_methods.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # This cop looks for delegations to predicate methods with `allow_nil: true` option.
+ # This construct results in three possible results: true, false and nil.
+ # In other words, it does not preserve the strict Boolean nature of predicate method return value.
+ # This cop suggests creating a method to handle `nil` delegator and ensure only Boolean type is returned.
+ #
+ # @example
+ # # bad
+ # delegate :is_foo?, to: :bar, allow_nil: true
+ #
+ # # good
+ # def is_foo?
+ # return false unless bar
+ # bar.is_foo?
+ # end
+ #
+ # def is_foo?
+ # !!bar&.is_foo?
+ # end
+ class DelegatePredicateMethods < RuboCop::Cop::Cop
+ MSG = "Using `delegate` with `allow_nil` on the following predicate methods is discouraged: %s."
+ RESTRICT_ON_SEND = %i[delegate].freeze
+ def_node_matcher :predicate_allow_nil_option, <<~PATTERN
+ (send nil? :delegate
+ (sym $_)*
+ (hash <$(pair (sym :allow_nil) true) ...>)
+ )
+ PATTERN
+
+ def on_send(node)
+ predicate_allow_nil_option(node) do |delegated_methods, _options|
+ offensive_methods = delegated_methods.select { |method| method.end_with?('?') }
+ next if offensive_methods.empty?
+
+ add_offense(node, message: format(MSG, offensive_methods.join(', ')))
+ end
+ end
+ end
+ end
+ end
+end