class RuboCop::Cop::Lint::MissingSuper

Checks for the presence of constructors and lifecycle callbacks without calls to ‘super`.

This cop does not consider ‘method_missing` (and `respond_to_missing?`) because in some cases it makes sense to overtake what is considered a missing method. In other cases, the theoretical ideal handling could be challenging or verbose for no actual gain.

Autocorrection is not supported because the position of ‘super` cannot be determined automatically.

‘Object` and `BasicObject` are allowed by this cop because of their stateless nature. However, sometimes you might want to allow other parent classes from this cop, for example in the case of an abstract class that is not meant to be called with `super`. In those cases, you can use the `AllowedParentClasses` option to specify which classes should be allowed *in addition to* `Object` and `BasicObject`.

@example

# bad
class Employee < Person
  def initialize(name, salary)
    @salary = salary
  end
end

# good
class Employee < Person
  def initialize(name, salary)
    super(name)
    @salary = salary
  end
end

# bad
Employee = Class.new(Person) do
  def initialize(name, salary)
    @salary = salary
  end
end

# good
Employee = Class.new(Person) do
  def initialize(name, salary)
    super(name)
    @salary = salary
  end
end

# bad
class Parent
  def self.inherited(base)
    do_something
  end
end

# good
class Parent
  def self.inherited(base)
    super
    do_something
  end
end

# good
class ClassWithNoParent
  def initialize
    do_something
  end
end

@example AllowedParentClasses: [MyAbstractClass]

# good
class MyConcreteClass < MyAbstractClass
  def initialize
    do_something
  end
end

Constants

CALLBACKS
CALLBACK_MSG
CLASS_LIFECYCLE_CALLBACKS
CONSTRUCTOR_MSG
METHOD_LIFECYCLE_CALLBACKS
STATELESS_CLASSES

Public Instance Methods

on_def(node) click to toggle source
# File lib/rubocop/cop/lint/missing_super.rb, line 105
def on_def(node)
  return unless offender?(node)

  if node.method?(:initialize) && inside_class_with_stateful_parent?(node)
    add_offense(node, message: CONSTRUCTOR_MSG)
  elsif callback_method_def?(node)
    add_offense(node, message: CALLBACK_MSG)
  end
end
on_defs(node) click to toggle source
# File lib/rubocop/cop/lint/missing_super.rb, line 115
def on_defs(node)
  return if !callback_method_def?(node) || contains_super?(node)

  add_offense(node, message: CALLBACK_MSG)
end

Private Instance Methods

allowed_class?(node) click to toggle source
# File lib/rubocop/cop/lint/missing_super.rb, line 149
def allowed_class?(node)
  allowed_classes.include?(node.const_name)
end
allowed_classes() click to toggle source
# File lib/rubocop/cop/lint/missing_super.rb, line 153
def allowed_classes
  @allowed_classes ||= STATELESS_CLASSES + cop_config.fetch('AllowedParentClasses', [])
end
callback_method_def?(node) click to toggle source
# File lib/rubocop/cop/lint/missing_super.rb, line 127
def callback_method_def?(node)
  return false unless CALLBACKS.include?(node.method_name)

  node.each_ancestor(:class, :sclass, :module).first
end
contains_super?(node) click to toggle source
# File lib/rubocop/cop/lint/missing_super.rb, line 133
def contains_super?(node)
  node.each_descendant(:super, :zsuper).any?
end
inside_class_with_stateful_parent?(node) click to toggle source
# File lib/rubocop/cop/lint/missing_super.rb, line 137
def inside_class_with_stateful_parent?(node)
  if (block_node = node.each_ancestor(:block, :numblock).first)
    return false unless (super_class = class_new_block(block_node))

    !allowed_class?(super_class)
  elsif (class_node = node.each_ancestor(:class).first)
    class_node.parent_class && !allowed_class?(class_node.parent_class)
  else
    false
  end
end
offender?(node) click to toggle source
# File lib/rubocop/cop/lint/missing_super.rb, line 123
def offender?(node)
  (node.method?(:initialize) || callback_method_def?(node)) && !contains_super?(node)
end