literal 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,4 +11,10 @@ class Literal::Types::NilableType
11
11
  def ===(value)
12
12
  nil === value || @type === value
13
13
  end
14
+
15
+ def record_literal_type_errors(ctx)
16
+ @type.record_literal_type_errors(ctx) if @type.respond_to?(:record_literal_type_errors)
17
+ end
18
+
19
+ freeze
14
20
  end
@@ -17,4 +17,14 @@ class Literal::Types::SetType
17
17
 
18
18
  true
19
19
  end
20
+
21
+ def record_literal_type_errors(context)
22
+ return unless Set === context.actual
23
+
24
+ context.actual.each do |actual|
25
+ unless @type === actual
26
+ context.add_child(label: "[]", expected: @type, actual:)
27
+ end
28
+ end
29
+ end
20
30
  end
@@ -23,4 +23,20 @@ class Literal::Types::TupleType
23
23
 
24
24
  true
25
25
  end
26
+
27
+ def record_literal_type_errors(context)
28
+ return unless Array === context.actual
29
+
30
+ len = [@types.size, context.actual.size].max
31
+ i = 0
32
+ while i < len
33
+ actual = context.actual[i]
34
+ if !(expected = @types[i])
35
+ context.add_child(label: "[#{i}]", expected: Literal::Types::NeverType, actual:)
36
+ elsif !(expected === actual)
37
+ context.add_child(label: "[#{i}]", expected:, actual:)
38
+ end
39
+ i += 1
40
+ end
41
+ end
26
42
  end
@@ -39,6 +39,13 @@ class Literal::Types::UnionType
39
39
  end
40
40
  end
41
41
 
42
+ def record_literal_type_errors(ctx)
43
+ @types.each do |type|
44
+ ctx.add_child(label: type.inspect, expected: type, actual: ctx.actual)
45
+ end
46
+ ctx.children.clear if ctx.children.none? { |c| c.children.any? }
47
+ end
48
+
42
49
  protected
43
50
 
44
51
  attr_reader :types
data/lib/literal/types.rb CHANGED
@@ -32,15 +32,15 @@ module Literal::Types
32
32
  autoload :UnionType, "literal/types/union_type"
33
33
  autoload :VoidType, "literal/types/void_type"
34
34
 
35
- NilableBooleanType = NilableType.new(BooleanType)
36
- NilableCallableType = NilableType.new(CallableType)
37
- NilableJSONDataType = NilableType.new(JSONDataType)
38
- NilableLambdaType = NilableType.new(LambdaType)
39
- NilableProcableType = NilableType.new(ProcableType)
35
+ NilableBooleanType = NilableType.new(BooleanType::Instance).freeze
36
+ NilableCallableType = NilableType.new(CallableType::Instance).freeze
37
+ NilableJSONDataType = NilableType.new(JSONDataType).freeze
38
+ NilableLambdaType = NilableType.new(LambdaType).freeze
39
+ NilableProcableType = NilableType.new(ProcableType).freeze
40
40
 
41
- # Matches any value except `nil`. Use `_Any?` or `_Unit` to match any value including `nil`.
41
+ # Matches any value except `nil`. Use `_Any?` or `_Void` to match any value including `nil`.
42
42
  def _Any
43
- AnyType
43
+ AnyType::Instance
44
44
  end
45
45
 
46
46
  def _Any?
@@ -61,7 +61,7 @@ module Literal::Types
61
61
 
62
62
  # Matches if the value is `true` or `false`.
63
63
  def _Boolean
64
- BooleanType
64
+ BooleanType::Instance
65
65
  end
66
66
 
67
67
  # Nilable version of `_Boolean`
@@ -71,7 +71,7 @@ module Literal::Types
71
71
 
72
72
  # Matches if the value responds to `#call`.
73
73
  def _Callable
74
- CallableType
74
+ CallableType::Instance
75
75
  end
76
76
 
77
77
  # Nilabl version of `_Callable`
@@ -131,7 +131,7 @@ module Literal::Types
131
131
 
132
132
  # Matches *"falsy"* values (`nil` and `false`).
133
133
  def _Falsy
134
- FalsyType
134
+ FalsyType::Instance
135
135
  end
136
136
 
137
137
  # Matches if the value is a `Float` and matches the given constraint.
@@ -166,9 +166,9 @@ module Literal::Types
166
166
  end
167
167
 
168
168
  # Nilable version of `_Hash`
169
- def _Hash?
169
+ def _Hash?(...)
170
170
  NilableType.new(
171
- HashType.new,
171
+ HashType.new(...),
172
172
  )
173
173
  end
174
174
 
@@ -184,7 +184,7 @@ module Literal::Types
184
184
  # Nilable version of `_Integer`
185
185
  def _Integer?(...)
186
186
  NilableType.new(
187
- IntegerType(...),
187
+ IntegerType.new(...),
188
188
  )
189
189
  end
190
190
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Literal
4
- VERSION = "1.0.0"
4
+ VERSION = "1.2.0"
5
5
  end
data/lib/literal.rb CHANGED
@@ -3,15 +3,24 @@
3
3
  module Literal
4
4
  TYPE_CHECKS_DISABLED = ENV["LITERAL_TYPE_CHECKS"] == "false"
5
5
 
6
+ autoload :Array, "literal/array"
6
7
  autoload :Data, "literal/data"
7
8
  autoload :DataProperty, "literal/data_property"
8
9
  autoload :DataStructure, "literal/data_structure"
9
10
  autoload :Enum, "literal/enum"
11
+ autoload :Flags, "literal/flags"
12
+ autoload :Flags16, "literal/flags"
13
+ autoload :Flags32, "literal/flags"
14
+ autoload :Flags64, "literal/flags"
15
+ autoload :Flags8, "literal/flags"
16
+ autoload :Hash, "literal/hash"
10
17
  autoload :Null, "literal/null"
11
18
  autoload :Object, "literal/object"
12
19
  autoload :Properties, "literal/properties"
13
20
  autoload :Property, "literal/property"
21
+ autoload :Set, "literal/set"
14
22
  autoload :Struct, "literal/struct"
23
+ autoload :Type, "literal/type"
15
24
  autoload :Types, "literal/types"
16
25
 
17
26
  # Errors
@@ -19,12 +28,89 @@ module Literal
19
28
  autoload :TypeError, "literal/errors/type_error"
20
29
  autoload :ArgumentError, "literal/errors/argument_error"
21
30
 
31
+ TRANSFORMS = {
32
+ Integer => {
33
+ abs: Integer,
34
+ ceil: Integer,
35
+ chr: String,
36
+ denominator: Integer,
37
+ even?: Types::BooleanType::Instance,
38
+ floor: Integer,
39
+ hash: Integer,
40
+ inspect: String,
41
+ integer?: true,
42
+ magnitude: Integer,
43
+ negative?: Types::BooleanType::Instance,
44
+ next: Integer,
45
+ nonzero?: Types::BooleanType::Instance,
46
+ numerator: Integer,
47
+ odd?: Types::BooleanType::Instance,
48
+ ord: Integer,
49
+ positive?: Types::BooleanType::Instance,
50
+ pred: Integer,
51
+ round: Integer,
52
+ size: Integer,
53
+ succ: Integer,
54
+ to_f: Float,
55
+ to_i: Integer,
56
+ to_int: Integer,
57
+ to_r: Rational,
58
+ to_s: String,
59
+ truncate: Integer,
60
+ zero?: Types::BooleanType::Instance,
61
+ },
62
+ String => {
63
+ ascii_only?: Types::BooleanType::Instance,
64
+ bytesize: Integer,
65
+ capitalize: String,
66
+ chomp: String,
67
+ chop: String,
68
+ downcase: String,
69
+ dump: String,
70
+ empty?: Types::BooleanType::Instance,
71
+ hash: Integer,
72
+ inspect: String,
73
+ length: Integer,
74
+ lstrip: String,
75
+ ord: Integer,
76
+ reverse: String,
77
+ rstrip: String,
78
+ scrub: String,
79
+ size: Integer,
80
+ strip: String,
81
+ swapcase: String,
82
+ to_str: String,
83
+ upcase: String,
84
+ valid_encoding?: Types::BooleanType::Instance,
85
+ },
86
+ Array => {
87
+ size: Integer,
88
+ length: Integer,
89
+ empty?: Types::BooleanType::Instance,
90
+ sort: Array,
91
+ to_a: Array,
92
+ to_ary: Array,
93
+ },
94
+ }.transform_values! { |it| it.transform_keys(&:to_proc) }.freeze
95
+
22
96
  def self.Enum(type)
23
97
  Class.new(Literal::Enum) do
24
98
  prop :value, type, :positional
25
99
  end
26
100
  end
27
101
 
102
+ def self.Array(type)
103
+ Literal::Array::Generic.new(type)
104
+ end
105
+
106
+ def self.Set(type)
107
+ Literal::Set::Generic.new(type)
108
+ end
109
+
110
+ def self.Hash(key_type, value_type)
111
+ Literal::Hash::Generic.new(key_type, value_type)
112
+ end
113
+
28
114
  def self.check(actual:, expected:)
29
115
  if expected === actual
30
116
  true
@@ -35,6 +121,17 @@ module Literal
35
121
  raise Literal::TypeError.new(context:)
36
122
  end
37
123
  end
124
+
125
+ def self.subtype?(type, of:)
126
+ (of == type) || case of
127
+ when Literal::Type, Module
128
+ of >= type
129
+ when Range
130
+ of.cover?(type)
131
+ else
132
+ false
133
+ end
134
+ end
38
135
  end
39
136
 
40
137
  require_relative "literal/rails" if defined?(Rails)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: literal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Drapper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-01 00:00:00.000000000 Z
11
+ date: 2024-11-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A literal Ruby gem.
14
14
  email:
@@ -20,6 +20,7 @@ files:
20
20
  - LICENSE.txt
21
21
  - README.md
22
22
  - lib/literal.rb
23
+ - lib/literal/array.rb
23
24
  - lib/literal/data.rb
24
25
  - lib/literal/data_property.rb
25
26
  - lib/literal/data_structure.rb
@@ -27,6 +28,8 @@ files:
27
28
  - lib/literal/errors/argument_error.rb
28
29
  - lib/literal/errors/error.rb
29
30
  - lib/literal/errors/type_error.rb
31
+ - lib/literal/flags.rb
32
+ - lib/literal/hash.rb
30
33
  - lib/literal/null.rb
31
34
  - lib/literal/object.rb
32
35
  - lib/literal/properties.rb
@@ -36,9 +39,12 @@ files:
36
39
  - lib/literal/rails.rb
37
40
  - lib/literal/rails/enum_serializer.rb
38
41
  - lib/literal/rails/enum_type.rb
42
+ - lib/literal/rails/flags_type.rb
39
43
  - lib/literal/rails/patches/active_record.rb
40
44
  - lib/literal/railtie.rb
45
+ - lib/literal/set.rb
41
46
  - lib/literal/struct.rb
47
+ - lib/literal/type.rb
42
48
  - lib/literal/types.rb
43
49
  - lib/literal/types/any_type.rb
44
50
  - lib/literal/types/array_type.rb