diff options
Diffstat (limited to 'rubocop/cop/gitlab/delegate_predicate_methods.rb')
-rw-r--r-- | rubocop/cop/gitlab/delegate_predicate_methods.rb | 45 |
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 |