class RuboCop::Cop::Naming::PredicateName

Checks that predicate method names end with a question mark and do not start with a forbidden prefix.

A method is determined to be a predicate method if its name starts with one of the prefixes listed in the ‘NamePrefix` configuration. The list defaults to `is_`, `has_`, and `have_` but may be overridden.

Predicate methods must end with a question mark.

When ‘ForbiddenPrefixes` is also set (as it is by default), predicate methods which begin with a forbidden prefix are not allowed, even if they end with a `?`. These methods should be changed to remove the prefix.

@example NamePrefix: [‘is_’, ‘has_’, ‘have_’] (default)

# bad
def is_even(value)
end

# When ForbiddenPrefixes: ['is_', 'has_', 'have_'] (default)
# good
def even?(value)
end

# When ForbiddenPrefixes: []
# good
def is_even?(value)
end

@example NamePrefix: [‘seems_to_be_’]

# bad
def seems_to_be_even(value)
end

# When ForbiddenPrefixes: ['seems_to_be_']
# good
def even?(value)
end

# When ForbiddenPrefixes: []
# good
def seems_to_be_even?(value)
end

@example AllowedMethods: [‘is_a?’] (default)

# Despite starting with the `is_` prefix, this method is allowed
# good
def is_a?(value)
end

@example AllowedMethods: [‘is_even?’]

# good
def is_even?(value)
end

@example MethodDefinitionMacros: [‘define_method’, ‘define_singleton_method’] (default)

# bad
define_method(:is_even) { |value| }

# good
define_method(:even?) { |value| }

@example MethodDefinitionMacros: [‘def_node_matcher’]

# bad
def_node_matcher(:is_even) { |value| }

# good
def_node_matcher(:even?) { |value| }

Public Instance Methods

on_def(node) click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 98
def on_def(node)
  predicate_prefixes.each do |prefix|
    method_name = node.method_name.to_s

    next if allowed_method_name?(method_name, prefix)

    add_offense(
      node.loc.name,
      message: message(method_name, expected_name(method_name, prefix))
    )
  end
end
Also aliased as: on_defs
on_defs(node)
Alias for: on_def
on_send(node) click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 85
def on_send(node)
  dynamic_method_define(node) do |method_name|
    predicate_prefixes.each do |prefix|
      next if allowed_method_name?(method_name.to_s, prefix)

      add_offense(
        node.first_argument,
        message: message(method_name, expected_name(method_name.to_s, prefix))
      )
    end
  end
end
validate_config() click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 112
        def validate_config
          forbidden_prefixes.each do |forbidden_prefix|
            next if predicate_prefixes.include?(forbidden_prefix)

            raise ValidationError, <<~MSG.chomp
              The `Naming/PredicateName` cop is misconfigured. Prefix #{forbidden_prefix} must be included in NamePrefix because it is included in ForbiddenPrefixes.
            MSG
          end
        end

Private Instance Methods

allowed_method_name?(method_name, prefix) click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 124
def allowed_method_name?(method_name, prefix)
  !(method_name.start_with?(prefix) && # cheap check to avoid allocating Regexp
      method_name.match?(/^#{prefix}[^0-9]/)) ||
    method_name == expected_name(method_name, prefix) ||
    method_name.end_with?('=') ||
    allowed_method?(method_name)
end
expected_name(method_name, prefix) click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 132
def expected_name(method_name, prefix)
  new_name = if forbidden_prefixes.include?(prefix)
               method_name.sub(prefix, '')
             else
               method_name.dup
             end
  new_name << '?' unless method_name.end_with?('?')
  new_name
end
forbidden_prefixes() click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 146
def forbidden_prefixes
  cop_config['ForbiddenPrefixes']
end
message(method_name, new_name) click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 142
def message(method_name, new_name)
  "Rename `#{method_name}` to `#{new_name}`."
end
method_definition_macros(macro_name) click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 154
def method_definition_macros(macro_name)
  cop_config['MethodDefinitionMacros'].include?(macro_name.to_s)
end
predicate_prefixes() click to toggle source
# File lib/rubocop/cop/naming/predicate_name.rb, line 150
def predicate_prefixes
  cop_config['NamePrefix']
end