Sha256: 5172aadadcd46ba249d2dc4b33b8e027324b3dabde06eaccd4282ef18eb70190

Contents?: true

Size: 1.94 KB

Versions: 119

Compression:

Stored size: 1.94 KB

Contents

# frozen_string_literal: true
# typed: true

module T::Private::Abstract::Declare
  Abstract = T::Private::Abstract
  AbstractUtils = T::AbstractUtils

  def self.declare_abstract(mod, type:)
    if AbstractUtils.abstract_module?(mod)
      raise "#{mod} is already declared as abstract"
    end
    if T::Private::Final.final_module?(mod)
      raise "#{mod} was already declared as final and cannot be declared as abstract"
    end

    Abstract::Data.set(mod, :can_have_abstract_methods, true)
    Abstract::Data.set(mod.singleton_class, :can_have_abstract_methods, true)
    Abstract::Data.set(mod, :abstract_type, type)

    mod.extend(Abstract::Hooks)
    mod.extend(T::InterfaceWrapper::Helpers)

    if mod.is_a?(Class)
      if type == :interface
        # Since `interface!` is just `abstract!` with some extra validation, we could technically
        # allow this, but it's unclear there are good use cases, and it might be confusing.
        raise "Classes can't be interfaces. Use `abstract!` instead of `interface!`."
      end

      if Object.instance_method(:method).bind_call(mod, :new).owner == mod
        raise "You must call `abstract!` *before* defining a `new` method"
      end

      # Don't need to silence warnings via without_ruby_warnings when calling
      # define_method because of the guard above

      mod.send(:define_singleton_method, :new) do |*args, &blk|
        super(*args, &blk).tap do |result|
          if result.instance_of?(mod)
            raise "#{mod} is declared as abstract; it cannot be instantiated"
          end
        end
      end

      # Ruby doesn not emit "method redefined" warnings for aliased methods
      # (more robust than undef_method that would create a small window in which the method doesn't exist)
      mod.singleton_class.send(:alias_method, :new, :new)

      if mod.singleton_class.respond_to?(:ruby2_keywords, true)
        mod.singleton_class.send(:ruby2_keywords, :new)
      end
    end
  end
end

Version data entries

119 entries across 113 versions & 2 rubygems

Version Path
sorbet-runtime-0.5.11143 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11142 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11141 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11139 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11132 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11128 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11122 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11120 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11119 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11116 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11114 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11109 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11108 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11105 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11104 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11097 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11094 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11090 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11089 lib/types/private/abstract/declare.rb
sorbet-runtime-0.5.11088 lib/types/private/abstract/declare.rb