Runtime assertions for Ruby literal.fun
ruby
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

Test more types

+300 -287
+2
Gemfile
··· 9 9 gem "rubocop" 10 10 gem "benchmark-ips" 11 11 gem "solargraph" 12 + 13 + gem "ruby-lsp"
+15 -8
Gemfile.lock
··· 1 1 GIT 2 2 remote: https://github.com/joeldrapper/quickdraw.git 3 - revision: af21ac6409c32bedb1614c3f0b382f897eccaeec 3 + revision: d41066d6282dac01992262df9281d01c5d77cfa2 4 4 specs: 5 5 quickdraw (0.1.0) 6 6 ··· 18 18 benchmark-ips (2.13.0) 19 19 diff-lcs (1.5.1) 20 20 e2mmap (0.1.0) 21 - jaro_winkler (1.5.6) 21 + jaro_winkler (1.6.0) 22 22 json (2.7.2) 23 23 kramdown (2.4.0) 24 24 rexml 25 25 kramdown-parser-gfm (1.1.0) 26 26 kramdown (~> 2.0) 27 27 language_server-protocol (3.17.0.3) 28 - nokogiri (1.16.4-aarch64-linux) 28 + nokogiri (1.16.6-aarch64-linux) 29 29 racc (~> 1.4) 30 - nokogiri (1.16.4-arm-linux) 30 + nokogiri (1.16.6-arm-linux) 31 31 racc (~> 1.4) 32 - nokogiri (1.16.4-arm64-darwin) 32 + nokogiri (1.16.6-arm64-darwin) 33 33 racc (~> 1.4) 34 - nokogiri (1.16.4-x86-linux) 34 + nokogiri (1.16.6-x86-linux) 35 35 racc (~> 1.4) 36 - nokogiri (1.16.4-x86_64-darwin) 36 + nokogiri (1.16.6-x86_64-darwin) 37 37 racc (~> 1.4) 38 - nokogiri (1.16.4-x86_64-linux) 38 + nokogiri (1.16.6-x86_64-linux) 39 39 racc (~> 1.4) 40 40 parallel (1.25.1) 41 41 parser (3.3.3.0) 42 42 ast (~> 2.4.1) 43 43 racc 44 + prism (0.29.0) 44 45 racc (1.8.0) 45 46 rainbow (3.1.1) 46 47 rbs (2.8.4) ··· 62 63 unicode-display_width (>= 2.4.0, < 3.0) 63 64 rubocop-ast (1.31.3) 64 65 parser (>= 3.3.1.0) 66 + ruby-lsp (0.17.2) 67 + language_server-protocol (~> 3.17.0) 68 + prism (>= 0.29.0, < 0.30) 69 + sorbet-runtime (>= 0.5.10782) 65 70 ruby-progressbar (1.13.0) 66 71 solargraph (0.50.0) 67 72 backport (~> 1.2) ··· 79 84 thor (~> 1.0) 80 85 tilt (~> 2.0) 81 86 yard (~> 0.9, >= 0.9.24) 87 + sorbet-runtime (0.5.11435) 82 88 strscan (3.1.0) 83 89 thor (1.3.1) 84 90 tilt (2.3.0) ··· 98 104 literal! 99 105 quickdraw! 100 106 rubocop 107 + ruby-lsp 101 108 solargraph 102 109 103 110 BUNDLED WITH
-1
lib/literal.rb
··· 2 2 3 3 module Literal 4 4 TYPE_CHECKS = ENV["LITERAL_TYPE_CHECKS"] != "false" 5 - EXPENSIVE_TYPE_CHECKS = ENV["LITERAL_EXPENSIVE_TYPE_CHECKS"] != "false" 6 5 7 6 autoload :Attributable, "literal/attributable" 8 7 autoload :Attribute, "literal/attribute"
+1 -1
lib/literal.test.rb
··· 1 1 # frozen_string_literal: true 2 2 3 3 test do 4 - expect(Literal::VERSION).to_be_a(String) 4 + expect(Literal::VERSION).to_be_a String 5 5 end
-7
lib/literal/generic.rb
··· 1 - # frozen_string_literal: true 2 - 3 - # @api private 4 - class Literal::Generic 5 - extend Literal::Modifiers::Abstract 6 - abstract! 7 - end
-19
lib/literal/hash.rb
··· 1 - # frozen_string_literal: true 2 - 3 - class Literal::Hash 4 - def initialize(value, key_type:, value_type:) 5 - @value = value 6 - @key_type = key_type 7 - @value_type = value_type 8 - end 9 - 10 - attr_accessor :value, :key_type, :value_type 11 - 12 - def []=(key, value) 13 - if @key_type === key && @value_type === value 14 - @value[key] = value 15 - else 16 - raise Literal::TypeError 17 - end 18 - end 19 - end
-24
lib/literal/hash_type.rb
··· 1 - # frozen_string_literal: true 2 - 3 - # @api private 4 - class Literal::HashType 5 - def initialize(key_type, value_type) 6 - @key_type = key_type 7 - @value_type = value_type 8 - end 9 - 10 - def inspect = "Hash(#{@key_type}, #{@value_type})" 11 - 12 - def ===(value) 13 - case value 14 - when Literal::Hash 15 - @key_type == value.key_type && @value_type == value.value_type 16 - else 17 - false 18 - end 19 - end 20 - 21 - def new(value) 22 - Literal::Hash.new(value, key_type: @key_type, value_type: @value_type) 23 - end 24 - end
+109 -106
lib/literal/types.rb
··· 7 7 autoload :CallableType, "literal/types/callable_type" 8 8 autoload :ClassType, "literal/types/class_type" 9 9 autoload :ConstraintType, "literal/types/constraint_type" 10 - autoload :DependantType, "literal/types/dependant_type" 10 + autoload :DescendantType, "literal/types/descendant_type" 11 11 autoload :EnumerableType, "literal/types/enumerable_type" 12 12 autoload :FalsyType, "literal/types/falsy_type" 13 - autoload :LambdaType, "literal/types/lambda_type" 13 + autoload :FloatType, "literal/types/float_type" 14 14 autoload :FrozenType, "literal/types/frozen_type" 15 - autoload :JSONDataType, "literal/types/json_data_type" 15 + autoload :HashType, "literal/types/hash_type" 16 + autoload :IntegerType, "literal/types/integer_type" 16 17 autoload :InterfaceType, "literal/types/interface_type" 18 + autoload :IntersectionType, "literal/types/intersection_type" 19 + autoload :JSONDataType, "literal/types/json_data_type" 20 + autoload :LambdaType, "literal/types/lambda_type" 21 + autoload :MapType, "literal/types/map_type" 22 + autoload :NeverType, "literal/types/never_type" 23 + autoload :NilableType, "literal/types/nilable_type" 17 24 autoload :NotType, "literal/types/not_type" 25 + autoload :ProcableType, "literal/types/procable_type" 26 + autoload :RangeType, "literal/types/range_type" 18 27 autoload :SetType, "literal/types/set_type" 19 - autoload :TupleType, "literal/types/tuple_type" 20 - autoload :IntegerType, "literal/types/integer_type" 21 - autoload :TruthyType, "literal/types/truthy_type" 22 - autoload :FloatType, "literal/types/float_type" 23 - autoload :HashType, "literal/types/hash_type" 28 + autoload :ShapeType, "literal/types/shape_type" 24 29 autoload :StringType, "literal/types/string_type" 25 - autoload :NeverType, "literal/types/never_type" 26 - 27 - # Matches if *any* given type is matched. 28 - def _Union(*types) 29 - raise Literal::ArgumentError.new("_Union type must have at least one type.") if types.size < 1 30 + autoload :SymbolType, "literal/types/symbol_type" 31 + autoload :TruthyType, "literal/types/truthy_type" 32 + autoload :TupleType, "literal/types/tuple_type" 33 + autoload :VoidType, "literal/types/void_type" 30 34 31 - Literal::Union.new(*types) 35 + # Matches any value except `nil`. Use `_Nilable(_Any)` to match any value including `nil`. 36 + def _Any 37 + Literal::Types::AnyType 32 38 end 33 39 34 - # Matches if *all* given types are matched. 35 - def _Intersection(*types) 36 - raise Literal::ArgumentError.new("_Intersection type must have at least one type.") if types.size < 1 40 + # Matches if the value is an `Array` and all the elements match the given type. 41 + def _Array(type) 42 + Literal::Types::ArrayType.new(type) 43 + end 37 44 38 - Literal::Types::IntersectionType.new(*types) 45 + # Matches if the value is `true` or `false`. 46 + def _Boolean 47 + Literal::Types::BooleanType 39 48 end 40 49 41 - # Matches if the given predicates are truthy. 42 - def _Is(*predicates) 43 - raise Literal::ArgumentError.new("_Is type must have at least one predicate.") if predicates.size < 1 50 + # Matches if the value responds to `#call`. 51 + def _Callable(type = nil) 52 + Literal::Types::CallableType 53 + end 44 54 45 - Literal::Types::IsType.new(*predicates) 55 + # Matches if the value either the given class or a subclass of it. 56 + def _Class(type) 57 + Literal::Types::ClassType.new(type) 46 58 end 47 59 48 - # Matches if the value is an `Array` and all the elements match the given type. 49 - def _Array(type) 50 - Literal::Types::ArrayType.new(type) 60 + # Similar to `_Intersection`, but allows you to specify attribute constraints as keyword arguments. 61 + # @example 62 + # _Constraint(Array, size: 1..3) 63 + def _Constraint(*constraints, **attributes) 64 + Literal::Types::ConstraintType.new(*constraints, **attributes) 51 65 end 52 66 53 - # Matches if the value is a `Set` and all the elements match the given type. 54 - def _Set(type) 55 - Literal::Types::SetType.new(type) 67 + # Matches if the value is a descendant of the given class. 68 + def _Descendant(type) 69 + Literal::Types::DescendantType.new(type) 56 70 end 57 71 58 - #  Matches if the value is an `Enumerable` and all the elements match the given type. 72 + #  Matches if the value is an `Enumerable` and all its elements match the given type. 59 73 def _Enumerable(type) 60 74 Literal::Types::EnumerableType.new(type) 61 75 end 62 76 77 + # Matches *"falsy"* values (`nil` and `false`). 78 + def _Falsy 79 + Literal::Types::FalsyType 80 + end 81 + 82 + # Matches if the value is a `Float` and matches the given constraint. 83 + # You could use a `Range`, for example, as a constraint. 84 + # If you don't need a constraint, use `Float` instead of `_Float`. 85 + def _Float(constraint) 86 + Literal::Types::FloatType.new(constraint) 87 + end 88 + 89 + # Matches if the value is *frozen*. 90 + def _Frozen(type) 91 + Literal::Types::FrozenType.new(type) 92 + end 93 + 63 94 # Matches if the value is a `Hash` and all the keys and values match the given types. 64 95 def _Hash(key_type, value_type) 65 96 Literal::Types::HashType.new(key_type, value_type) 66 97 end 67 98 99 + # Matches if the value is an `Integer` and matches the given constraint. 100 + # You could use a `Range`, for example, as a constraint. 101 + # If you don't need a constraint, use `Integer` instead of `_Integer`. 102 + # @example 103 + # attribute :age, _Integer(18..127) 104 + def _Integer(constraint) 105 + Literal::Types::IntegerType.new(constraint) 106 + end 107 + 68 108 # Matches if the value responds to all the given methods. 69 109 def _Interface(*methods) 70 110 raise Literal::ArgumentError.new("_Interface type must have at least one method.") if methods.size < 1 ··· 72 112 Literal::Types::InterfaceType.new(*methods) 73 113 end 74 114 75 - # Matches if the value is either `nil` or the given type. 76 - def _Nilable(type) 77 - Literal::Types::NilableType.new(type) 115 + # Matches if *all* given types are matched. 116 + def _Intersection(*types) 117 + raise Literal::ArgumentError.new("_Intersection type must have at least one type.") if types.size < 1 118 + 119 + Literal::Types::IntersectionType.new(*types) 78 120 end 79 121 80 - # Matches any value except `nil`. Use `_Nilable(_Any)` to match any value including `nil`. 81 - def _Any 82 - Literal::Types::AnyType 122 + # Ensures the value is valid JSON data (i.e. it came from JSON.parse). 123 + def _JSONData 124 + Literal::Types::JSONDataType 83 125 end 84 126 85 - # Matches if the value is `true` or `false`. 86 - def _Boolean 87 - Literal::Types::BooleanType 127 + # Matches if the value is a `Proc` and `#lambda?` returns truthy. 128 + def _Lambda 129 + Literal::Types::LambdaType 88 130 end 89 131 90 - # Matches if the value either the given class or a subclass of it. 91 - def _Class(type) 92 - Literal::Types::ClassType.new(type) 132 + def _Map(**shape) 133 + Literal::Types::MapType 93 134 end 94 135 95 - # Matches if the value is an `Array` and each element matches the given types in order. 96 - def _Tuple(*types) 97 - raise Literal::ArgumentError.new("_Tuple type must have at least one type.") if types.size < 1 136 + # Never matches any value. 137 + def _Never 138 + Literal::Types::NeverType 139 + end 98 140 99 - Literal::Types::TupleType.new(*types) 141 + # Matches if the value is either `nil` or the given type. 142 + def _Nilable(type) 143 + Literal::Types::NilableType.new(type) 100 144 end 101 145 102 - # Matches if the value is an `Integer` and matches the given constraint. 103 - # You could use a `Range`, for example, as a constraint. 104 - # If you don't need a constraint, use `Integer` instead of `_Integer`. 105 - # @example 106 - # attribute :age, _Integer(18..127) 107 - def _Integer(constraint) 108 - Literal::Types::IntegerType.new(constraint) 146 + # Matches if the given type is *not* matched. 147 + def _Not(type) 148 + Literal::Types::NotType.new(type) 109 149 end 110 150 111 - # Matches if the value is a `Float` and matches the given constraint. 112 - # You could use a `Range`, for example, as a constraint. 113 - # If you don't need a constraint, use `Float` instead of `_Float`. 114 - def _Float(constraint) 115 - Literal::Types::FloatType.new(constraint) 151 + # Matches if the value is a `Proc` or responds to `#to_proc`. 152 + def _Procable 153 + Literal::Types::ProcableType 116 154 end 117 155 118 156 # Matches if the value is a `Range` of the given type. ··· 120 158 Literal::Types::RangeType.new(type) 121 159 end 122 160 123 - # Matches if the value responds to `#call`. 124 - def _Callable(type = nil) 125 - Literal::Types::CallableType 161 + # Matches if the value is a `Set` and all the elements match the given type. 162 + def _Set(type) 163 + Literal::Types::SetType.new(type) 126 164 end 127 165 128 - # Matches if the value is a `Proc` or responds to `#to_proc`. 129 - def _Procable 130 - Literal::Types::ProcableType 131 - end 132 - 133 - # Matches if the value is a `Proc` and `#lambda?` returns truthy. 134 - def _Lambda 135 - Literal::Types::LambdaType 166 + # Ensures a value matches the given shape of a Hash 167 + def _Shape(*constraints, **shape) 168 + Literal::Types::ShapeType.new(*constraints, **shape) 136 169 end 137 170 138 171 # Matches if the value is a `String` and matches the given constraint. ··· 147 180 Literal::Types::SymbolType.new(constraint) 148 181 end 149 182 150 - # Matches if the given type is *not* matched. 151 - def _Not(type) 152 - Literal::Types::NotType.new(type) 153 - end 154 - 155 183 # Matches *"truthy"* values (anything except `nil` and `false`). 156 184 def _Truthy 157 185 Literal::Types::TruthyType 158 186 end 159 187 160 - # Matches *"falsy"* values (`nil` and `false`). 161 - def _Falsy 162 - Literal::Types::FalsyType 163 - end 188 + # Matches if the value is an `Array` and each element matches the given types in order. 189 + def _Tuple(*types) 190 + raise Literal::ArgumentError.new("_Tuple type must have at least one type.") if types.size < 1 164 191 165 - # Ensures a value matches the given shape of a Hash 166 - def _Shape(*constraints, **shape) 167 - Literal::Types::ShapeType.new(*constraints, **shape) 192 + Literal::Types::TupleType.new(*types) 168 193 end 169 194 170 - # Ensures the value is valid JSON data (i.e. it came from JSON.parse). 171 - def _JSONData 172 - Literal::Types::JSONDataType 173 - end 195 + # Matches if *any* given type is matched. 196 + def _Union(*types) 197 + raise Literal::ArgumentError.new("_Union type must have at least one type.") if types.size < 1 174 198 175 - # Matches if the value is *frozen*. 176 - def _Frozen(type) 177 - Literal::Types::FrozenType.new(type) 178 - end 179 - 180 - # Similar to `_Intersection`, but allows you to specify attribute constraints as keyword arguments. 181 - # @example 182 - # _Constraint(Array, size: 1..3) 183 - def _Constraint(*constraints, **attributes) 184 - Literal::Types::ConstraintType.new(*constraints, **attributes) 199 + Literal::Union.new(*types) 185 200 end 186 201 187 202 def _Void 188 203 Literal::Types::VoidType 189 - end 190 - 191 - def _Map(**shape) 192 - Literal::Types::MapType 193 - end 194 - 195 - def _Never 196 - Literal::Types::NeverType 197 - end 198 - 199 - def _Descendant(type) 200 - Literal::Types::DescendantType.new(type) 201 204 end 202 205 end
+153
lib/literal/types.test.rb
··· 1 + # frozen_string_literal: true 2 + 3 + include Literal::Types 4 + 5 + test "_Any" do 6 + Fixtures::Objects.each do |object| 7 + assert AnyType === object 8 + end 9 + 10 + refute AnyType === nil 11 + end 12 + 13 + test "_Array" do 14 + assert _Array(String) === [] 15 + assert _Array(String) === ["a", "b", "c"] 16 + 17 + refute _Array(String) === ["a", "b", 42] 18 + end 19 + 20 + test "_Boolean" do 21 + assert _Boolean === true 22 + assert _Boolean === false 23 + 24 + refute _Boolean === nil 25 + end 26 + 27 + test "_Callable" do 28 + assert _Callable === -> {} 29 + assert _Callable === method(:puts) 30 + 31 + refute _Callable === nil 32 + end 33 + 34 + test "_Class" do 35 + assert _Class(Enumerable) === Array 36 + 37 + refute _Class(Enumerable) === [] 38 + refute _Class(Enumerable) === String 39 + refute _Class(Enumerable) === Enumerable 40 + end 41 + 42 + describe "_Constraint" do 43 + test "object constraints" do 44 + age_constraint = _Constraint(Integer, 18..) 45 + 46 + assert age_constraint === 18 47 + 48 + refute age_constraint === 17 49 + refute age_constraint === 17.5 50 + end 51 + 52 + test "attribute constraints" do 53 + age_constraint = _Constraint(Array, size: 2..3) 54 + 55 + assert age_constraint === [1, 2] 56 + assert age_constraint === [1, 2, 3] 57 + 58 + refute age_constraint === [1] 59 + refute age_constraint === [1, 2, 3, 4] 60 + refute age_constraint === Set[1, 2] 61 + end 62 + end 63 + 64 + test "_Descendant" do 65 + assert _Descendant(Enumerable) === Array 66 + assert _Descendant(Enumerable) === Set 67 + 68 + refute _Descendant(Enumerable) === [] 69 + refute _Descendant(Enumerable) === String 70 + end 71 + 72 + test "_Enumerable" do 73 + assert _Enumerable(String) === ["a", "b", "c"] 74 + assert _Enumerable(Integer) === Set[1, 2, 3] 75 + 76 + refute _Enumerable(String) === [1, "a", :symbol] 77 + end 78 + 79 + test "_Falsy" do 80 + falsy_objects = Set[false, nil] 81 + truthy_objects = Fixtures::Objects - falsy_objects 82 + 83 + falsy_objects.each do |object| 84 + assert _Falsy === object 85 + end 86 + 87 + truthy_objects.each do |object| 88 + refute _Falsy === object 89 + end 90 + end 91 + 92 + test "_Float" do 93 + assert _Float(18.0..) === 18.0 94 + assert _Float(18.0..) === 19.5 95 + 96 + refute _Float(18.0..) === 17.99 97 + refute _Float(18.0..) === 42 98 + refute _Float(18.0..) === "string" 99 + refute _Float(18.0..) === nil 100 + end 101 + 102 + test "_Frozen" do 103 + assert _Frozen(Array) === [].freeze 104 + assert _Frozen(String) === "immutable" 105 + 106 + refute _Frozen(Array) === [] 107 + refute _Frozen(String) === +"mutable" 108 + refute _Frozen(Array) === nil 109 + end 110 + 111 + test "_Hash" do 112 + assert _Hash(String, Integer) === { "a" => 1, "b" => 2 } 113 + assert _Hash(Symbol, String) === { foo: "bar", baz: "qux" } 114 + 115 + refute _Hash(String, Integer) === { "a" => "1", "b" => 2 } 116 + refute _Hash(String, Integer) === { 1 => 2, 3 => 4 } 117 + refute _Hash(Symbol, String) === { "foo" => "bar", :baz => "qux" } 118 + end 119 + 120 + test "_Integer" do 121 + assert _Integer(18..) === 18 122 + assert _Integer(18..) === 19 123 + 124 + refute _Integer(18..) === 17 125 + refute _Integer(18..) === 18.5 126 + refute _Integer(18..) === "string" 127 + refute _Integer(18..) === nil 128 + end 129 + 130 + test "_Interface" do 131 + enumerable_interface = _Interface(:each, :map, :select) 132 + 133 + assert enumerable_interface === [] 134 + assert enumerable_interface === Set.new 135 + 136 + refute enumerable_interface === 42 137 + refute enumerable_interface === "string" 138 + refute enumerable_interface === nil 139 + end 140 + 141 + test "_Never" do 142 + Fixtures::Objects.each do |object| 143 + refute _Never === object 144 + end 145 + 146 + refute _Never === nil 147 + end 148 + 149 + test "_Void" do 150 + Fixtures::Objects.each do |object| 151 + assert _Void === object 152 + end 153 + end
-11
lib/literal/types/any_type.test.rb
··· 1 - # frozen_string_literal: true 2 - 3 - include Literal::Types 4 - 5 - test "matches any type apart from nil" do 6 - Fixtures::Objects.each do |object| 7 - assert AnyType === object 8 - end 9 - 10 - refute AnyType === nil 11 - end
+2 -8
lib/literal/types/array_type.rb
··· 8 8 9 9 def inspect = "_Array(#{@type.inspect})" 10 10 11 - if Literal::EXPENSIVE_TYPE_CHECKS 12 - def ===(value) 13 - Array === value && value.all? { |item| @type === item } 14 - end 15 - else 16 - def ===(value) 17 - Array === value && (value.empty? || @type === value[0]) 18 - end 11 + def ===(value) 12 + Array === value && value.all? { |item| @type === item } 19 13 end 20 14 end
-16
lib/literal/types/boolean_type.test.rb
··· 1 - # frozen_string_literal: true 2 - 3 - include Literal::Types 4 - 5 - Booleans = Set[true, false] 6 - OtherObjects = Fixtures::Objects - Booleans 7 - 8 - test do 9 - Booleans.each do |value| 10 - assert BooleanType === value 11 - end 12 - 13 - OtherObjects.each do |value| 14 - refute BooleanType === value 15 - end 16 - end
+2 -8
lib/literal/types/enumerable_type.rb
··· 8 8 9 9 def inspect = "_Enumerable(#{@type.inspect})" 10 10 11 - if Literal::EXPENSIVE_TYPE_CHECKS 12 - def ===(value) 13 - Enumerable === value && value.all? { |item| @type === item } 14 - end 15 - else 16 - def ===(value) 17 - Enumerable === value && (value.empty? || @type === value.first) 18 - end 11 + def ===(value) 12 + Enumerable === value && value.all? { |item| @type === item } 19 13 end 20 14 end
-16
lib/literal/types/falsy_type.test.rb
··· 1 - # frozen_string_literal: true 2 - 3 - include Literal::Types 4 - 5 - FalsyObjects = Set[false, nil] 6 - TruthyObject = Fixtures::Objects - FalsyObjects 7 - 8 - test do 9 - FalsyObjects.each do |object| 10 - assert FalsyType === object 11 - end 12 - 13 - TruthyObject.each do |object| 14 - refute FalsyType === object 15 - end 16 - end
+2 -8
lib/literal/types/hash_type.rb
··· 9 9 10 10 def inspect = "_Hash(#{@key_type.inspect}, #{@value_type.inspect})" 11 11 12 - if Literal::EXPENSIVE_TYPE_CHECKS 13 - def ===(value) 14 - Hash === value && value.all? { |k, v| @key_type === k && @value_type === v } 15 - end 16 - else 17 - def ===(value) 18 - Hash === value && (value.empty? || (@key_type === value.each_key.first && @value_type === value.each_value.first)) 19 - end 12 + def ===(value) 13 + Hash === value && value.all? { |k, v| @key_type === k && @value_type === v } 20 14 end 21 15 end
-14
lib/literal/types/is_type.rb
··· 1 - # frozen_string_literal: true 2 - 3 - # @api private 4 - class Literal::Types::IsType 5 - def initialize(*predicates) 6 - @predicates = predicates 7 - end 8 - 9 - def inspect = "_Is(#{predicates.map(&:inspect).join(', ')})" 10 - 11 - def ===(value) 12 - @predicates.all? { |predicate| value.public_send(predicate) } 13 - end 14 - end
+10 -21
lib/literal/types/json_data_type.rb
··· 8 8 9 9 def inspect = "_JSONData" 10 10 11 - if Literal::EXPENSIVE_TYPE_CHECKS 12 - def ===(value) 13 - case value 14 - when String, Integer, Float, true, false, nil 15 - true 16 - when Hash 17 - value.all? { |k, v| String === k && self === v } 18 - when Array 19 - value.all? { |v| self === v } 20 - else 21 - false 22 - end 23 - end 24 - else 25 - def ===(value) 26 - case value 27 - when Hash, Array, String, Integer, Float, true, false, nil 28 - true 29 - else 30 - false 31 - end 11 + def ===(value) 12 + case value 13 + when String, Integer, Float, true, false, nil 14 + true 15 + when Hash 16 + value.all? { |k, v| String === k && self === v } 17 + when Array 18 + value.all? { |v| self === v } 19 + else 20 + false 32 21 end 33 22 end 34 23 end
-11
lib/literal/types/never_type.test.rb
··· 1 - # frozen_string_literal: true 2 - 3 - include Literal::Types 4 - 5 - test "never matches anything" do 6 - Fixtures::Objects.each do |object| 7 - refute NeverType === object 8 - end 9 - 10 - refute NeverType === nil 11 - end
+2 -8
lib/literal/types/set_type.rb
··· 8 8 9 9 def inspect = "_Set(#{@type.inspect})" 10 10 11 - if Literal::EXPENSIVE_TYPE_CHECKS 12 - def ===(value) 13 - Set === value && value.all? { |item| @type === item } 14 - end 15 - else 16 - def ===(value) 17 - Set === value && (value.empty? || @type === value.first) 18 - end 11 + def ===(value) 12 + Set === value && value.all? { |item| @type === item } 19 13 end 20 14 end
+2
lib/literal/visitor.rb
··· 15 15 end 16 16 end 17 17 end 18 + 19 + Literal.private_constant(:Visitor)