From c9c1173d1dcb8c1415ecf93b879e96226a646461 Mon Sep 17 00:00:00 2001 From: SamW Date: Sun, 26 Nov 2023 13:24:22 -0800 Subject: [PATCH] Added WithEnum#but and with_range --- test/stdlib/test_helper.rb | 42 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/test/stdlib/test_helper.rb b/test/stdlib/test_helper.rb index 42d2acb9e6..0e81537656 100644 --- a/test/stdlib/test_helper.rb +++ b/test/stdlib/test_helper.rb @@ -179,11 +179,20 @@ def and_nil(&block) self.and(nil, &block) end + def but(*cases) + return WithEnum.new to_enum(__method__, *args) unless block_given? + + each do |arg| + yield arg unless cases.any? { _1 === arg } + end + end + def and(*args, &block) - return WithEnum.new to_enum(__method__, args) unless block_given? + return WithEnum.new to_enum(__method__, *args) unless block_given? + each(&block) args.each do |arg| - if WithEnum === arg + if WithEnum === arg # use `===` as `arg` might not have `.is_a?` on it arg.each(&block) else block.call(arg) @@ -192,6 +201,11 @@ def and(*args, &block) end end + def with(*args, &block) + return WithEnum.new to_enum(__method__, *args) unless block_given? + args.each(&block) + end + def with_int(value = 3) return WithEnum.new to_enum(__method__, value) unless block_given? yield value @@ -264,7 +278,31 @@ def with_boolish(&block) end alias with_untyped with_boolish + + def with_range(start, stop, exclude_end = false) + # If you need fixed starting and stopping points, you can just do `with_range with(1), with(2)`. + raise ArgumentError, '`start` must be from a `with` method' unless start.is_a? WithEnum + raise ArgumentError, '`stop` must be from a `with` method' unless stop.is_a? WithEnum + + start.each do |lower| + stop.each do |upper| + yield CustomRange.new(lower, upper, exclude_end) + + # `Range` requires `begin <=> end` to return non-nil, but doesn't actually + # end up using the return value of it. This is to add that in when needed. + def lower.<=>(rhs) = :not_nil unless defined? lower.<=> + + # If `lower <=> rhs` is defined but nil, then that means we're going to be constructing + # an illegal range (eg `3..ToInt.new(4)`). So, we need to skip yielding an invalid range + # in that case. + next if defined?(lower.<=>) && nil == (lower <=> upper) + + yield Range.new(lower, upper, exclude_end) + end + end + end end + module TypeAssertions module ClassMethods attr_reader :target