mirror of
https://github.com/Homebrew/brew.git
synced 2024-11-25 16:33:34 +08:00
Merge pull request #18801 from Homebrew/enforce-final
Enforce finalized sorbet methods
This commit is contained in:
commit
3a5b17a421
@ -77,6 +77,9 @@ class Formula
|
||||
extend Cachable
|
||||
extend Attrable
|
||||
extend APIHashable
|
||||
extend T::Helpers
|
||||
|
||||
abstract!
|
||||
|
||||
SUPPORTED_NETWORK_ACCESS_PHASES = [:build, :test, :postinstall].freeze
|
||||
private_constant :SUPPORTED_NETWORK_ACCESS_PHASES
|
||||
@ -1596,7 +1599,11 @@ class Formula
|
||||
|
||||
# Yields |self,staging| with current working directory set to the uncompressed tarball
|
||||
# where staging is a {Mktemp} staging context.
|
||||
def brew(fetch: true, keep_tmp: false, debug_symbols: false, interactive: false)
|
||||
sig(:final) {
|
||||
params(fetch: T::Boolean, keep_tmp: T::Boolean, debug_symbols: T::Boolean, interactive: T::Boolean,
|
||||
_blk: T.proc.params(arg0: Formula, arg1: Mktemp).void).void
|
||||
}
|
||||
def brew(fetch: true, keep_tmp: false, debug_symbols: false, interactive: false, &_blk)
|
||||
@prefix_returns_versioned_prefix = true
|
||||
active_spec.fetch if fetch
|
||||
stage(interactive:, debug_symbols:) do |staging|
|
||||
@ -3344,12 +3351,7 @@ class Formula
|
||||
def method_added(method)
|
||||
super
|
||||
|
||||
case method
|
||||
when :brew
|
||||
raise "You cannot override Formula#brew in class #{name}"
|
||||
when :test
|
||||
define_method(:test_defined?) { true }
|
||||
end
|
||||
define_method(:test_defined?) { true } if method == :test
|
||||
end
|
||||
|
||||
def freeze
|
||||
|
@ -13,14 +13,15 @@ require "build_environment"
|
||||
class Requirement
|
||||
include Dependable
|
||||
extend Cachable
|
||||
extend T::Helpers
|
||||
|
||||
# This base class enforces no constraints on its own.
|
||||
# Individual subclasses use the `satisfy` DSL to define those constraints.
|
||||
abstract!
|
||||
|
||||
attr_reader :name, :cask, :download
|
||||
|
||||
def initialize(tags = [])
|
||||
# Only allow instances of subclasses. This base class enforces no constraints on its own.
|
||||
# Individual subclasses use the `satisfy` DSL to define those constraints.
|
||||
raise "Do not call `Requirement.new' directly without a subclass." unless self.class < Requirement
|
||||
|
||||
@cask = self.class.cask
|
||||
@download = self.class.download
|
||||
tags.each do |tag|
|
||||
|
@ -8,7 +8,9 @@ require "extend/module"
|
||||
# In the future we should consider not doing this monkey patch,
|
||||
# if assured that there is no performance hit from removing this.
|
||||
# There are mechanisms to achieve a middle ground (`default_checked_level`).
|
||||
unless ENV["HOMEBREW_SORBET_RUNTIME"]
|
||||
if ENV["HOMEBREW_SORBET_RUNTIME"]
|
||||
T::Configuration.enable_final_checks_on_hooks
|
||||
else
|
||||
# Redefine `T.let`, etc. to make the `checked` parameter default to `false` rather than `true`.
|
||||
# @private
|
||||
module TNoChecks
|
||||
|
@ -60,6 +60,11 @@ RSpec.describe Formula do
|
||||
expect { klass.new }.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
specify "formula instantiation without a subclass" do
|
||||
expect { described_class.new(name, path, spec) }
|
||||
.to raise_error(RuntimeError, "Do not call `Formula.new' directly without a subclass.")
|
||||
end
|
||||
|
||||
context "when in a Tap" do
|
||||
let(:tap) { Tap.fetch("foo", "bar") }
|
||||
let(:path) { (tap.path/"Formula/#{name}.rb") }
|
||||
|
@ -24,7 +24,7 @@ RSpec.describe Formula do
|
||||
formula do
|
||||
def brew; end
|
||||
end
|
||||
end.to raise_error(RuntimeError, /You cannot override Formula#brew/)
|
||||
end.to raise_error(RuntimeError, /\AThe method `brew` on #{described_class} was declared as final/)
|
||||
end
|
||||
|
||||
it "validates the `name`" do
|
||||
|
@ -10,6 +10,13 @@ RSpec.describe Requirement do
|
||||
|
||||
let(:klass) { Class.new(described_class) }
|
||||
|
||||
describe "base class" do
|
||||
it "raises an error when instantiated" do
|
||||
expect { described_class.new }
|
||||
.to raise_error(RuntimeError, "Requirement is declared as abstract; it cannot be instantiated")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#tags" do
|
||||
subject(:req) { klass.new(tags) }
|
||||
|
||||
@ -52,6 +59,17 @@ RSpec.describe Requirement do
|
||||
describe "#fatal is omitted" do
|
||||
it { is_expected.not_to be_fatal }
|
||||
end
|
||||
|
||||
describe "in subclasses" do
|
||||
it "raises an error when instantiated" do
|
||||
expect do
|
||||
Class.new(described_class) do
|
||||
def fatal? = false
|
||||
end
|
||||
end
|
||||
.to raise_error(RuntimeError, /\AThe method `fatal\?` on #{described_class.name} was declared as final/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#satisfied?" do
|
||||
|
Loading…
Reference in New Issue
Block a user