taipo 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/README.md +8 -0
- data/lib/taipo/check.rb +2 -0
- data/lib/taipo/parser.rb +2 -2
- data/lib/taipo/parser/validater.rb +12 -0
- data/lib/taipo/type_element.rb +23 -5
- data/lib/taipo/type_element/child_type.rb +6 -1
- data/lib/taipo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ae496b6a69d19aceb9f158a587cb7c2f7d0faa1
|
4
|
+
data.tar.gz: ec0096547e644b51f8759529a246b273ff5354e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb51c506c37aaaca6232488649b8cf59246ea2a3f69e7efb5230b677e1c8d32e276949126202325ebea6c9e8f4d5f652287a47e0a6aa6afd08c23da0f4cd86eb
|
7
|
+
data.tar.gz: 6c1b5b0bb7512d4829167bb5d8400f204fb114cedf16350a0099f71a43a54139a5908c16f08d9a513f9ce23c6c4bbc80b0f4a29c1cd2289411f048bd295006c6
|
data/README.md
CHANGED
@@ -102,6 +102,14 @@ It's possible to specify a duck type by writing the instance method (or methods)
|
|
102
102
|
check types, a: '#to_s', b: '(#foo, #bar)'
|
103
103
|
```
|
104
104
|
|
105
|
+
#### Optional Types
|
106
|
+
|
107
|
+
If `nil` is permitted as a value, the optional shorthand `?` can be appended to the end of a class name to form an optional type. Collections and constraints can follow as usual.
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
check types, a: 'String?', b: 'Array?<Integer>', c: 'Integer?(min: 0)'
|
111
|
+
```
|
112
|
+
|
105
113
|
### Collections
|
106
114
|
|
107
115
|
Taipo can also check whether a variable has a collection of elements of the specified child type. A child type can consist of the same components as any other type (ie. a name, collection, constraint, sum).
|
data/lib/taipo/check.rb
CHANGED
@@ -88,6 +88,8 @@ module Taipo
|
|
88
88
|
unless collect_invalids || is_match
|
89
89
|
if Taipo::instance_method? v
|
90
90
|
msg = "Object '#{k}' does not respond to #{v}."
|
91
|
+
elsif Taipo::symbol? v
|
92
|
+
msg = "Object '#{k}' is not equal to #{v}."
|
91
93
|
elsif arg.is_a? Enumerable
|
92
94
|
type_def = Taipo.object_to_type_def arg
|
93
95
|
msg = "Object '#{k}' is #{type_def} but expected #{v}."
|
data/lib/taipo/parser.rb
CHANGED
@@ -35,7 +35,7 @@ module Taipo
|
|
35
35
|
|
36
36
|
case c
|
37
37
|
when '|'
|
38
|
-
unless attached? previous #
|
38
|
+
unless attached? previous # Previous character must have been '>' or ')'.
|
39
39
|
el = Taipo::TypeElement.new name: content
|
40
40
|
content = ''
|
41
41
|
elements = stack.pop
|
@@ -51,7 +51,7 @@ module Taipo
|
|
51
51
|
first_component = Array.new
|
52
52
|
stack.push first_component
|
53
53
|
when '>'
|
54
|
-
if attached? previous #
|
54
|
+
if attached? previous # Previous character must have been '>' or ')'.
|
55
55
|
last_component = stack.pop
|
56
56
|
else
|
57
57
|
el = Taipo::TypeElement.new name: content.strip
|
@@ -36,6 +36,18 @@ module Taipo
|
|
36
36
|
# parentheses can be omitted. For defining duck types that respond to
|
37
37
|
# multiple methods, the parentheses are required.
|
38
38
|
#
|
39
|
+
# ==== Optional Types
|
40
|
+
#
|
41
|
+
# 'String?', 'Array<Integer?>', 'Symbol?|String?'
|
42
|
+
#
|
43
|
+
# It is possible to specify an 'optional' type by appending a question mark
|
44
|
+
# to the name of the type. This shorthand functions similarly to defining a
|
45
|
+
# sum type with NilClass (the implementation of how optional types are
|
46
|
+
# checked is slightly different, however; see {Taipo::TypeElement#match?}).
|
47
|
+
# It is not possible to define an optional duck type. For that, either the
|
48
|
+
# implicit Object class should be specified (and then made optional), or a
|
49
|
+
# sum type should be used.
|
50
|
+
#
|
39
51
|
# === Collections
|
40
52
|
#
|
41
53
|
# 'Array<Integer>', 'Hash<Symbol, String>', 'Array<Array<Float>>'
|
data/lib/taipo/type_element.rb
CHANGED
@@ -136,6 +136,7 @@ module Taipo
|
|
136
136
|
# @since 1.0.0
|
137
137
|
# @api private
|
138
138
|
def match?(arg)
|
139
|
+
return true if optional? && arg.nil?
|
139
140
|
match_class?(arg) && match_constraints?(arg) && match_child_type?(arg)
|
140
141
|
end
|
141
142
|
|
@@ -150,12 +151,13 @@ module Taipo
|
|
150
151
|
# @since 1.0.0
|
151
152
|
# @api private
|
152
153
|
def match_class?(arg)
|
153
|
-
|
154
|
+
actual_name = (optional?) ? @name[0..-2] : @name
|
155
|
+
if actual_name == 'Boolean'
|
154
156
|
arg.is_a?(TrueClass) || arg.is_a?(FalseClass)
|
155
157
|
else
|
156
|
-
msg = "Class to match #{
|
157
|
-
raise Taipo::SyntaxError, msg unless Object.const_defined?(
|
158
|
-
arg.is_a? Object.const_get(
|
158
|
+
msg = "Class to match #{actual_name} is not defined"
|
159
|
+
raise Taipo::SyntaxError, msg unless Object.const_defined?(actual_name)
|
160
|
+
arg.is_a? Object.const_get(actual_name)
|
159
161
|
end
|
160
162
|
end
|
161
163
|
|
@@ -174,7 +176,7 @@ module Taipo
|
|
174
176
|
return false if !self_childless && arg_childless
|
175
177
|
|
176
178
|
arg.all? do |a|
|
177
|
-
if
|
179
|
+
if !arg.is_a?(Array) && a.is_a?(Array)
|
178
180
|
a.each.with_index.reduce(nil) do |memo,(component,index)|
|
179
181
|
result = @child_type[index].any? { |c| c.match? component }
|
180
182
|
(memo.nil?) ? result : memo && result
|
@@ -201,6 +203,22 @@ module Taipo
|
|
201
203
|
end
|
202
204
|
end
|
203
205
|
|
206
|
+
# Check whether this element is an optional
|
207
|
+
#
|
208
|
+
# An optional type is a variation on a normal type that also matches +nil+.
|
209
|
+
# Taipo borrows the syntax used in some other languages of denoting
|
210
|
+
# optional types by appending a question mark to the end of the class name.
|
211
|
+
#
|
212
|
+
# @note This merely checks whether +@name+ ends in a question mark.
|
213
|
+
#
|
214
|
+
# @return [Boolean] the result
|
215
|
+
#
|
216
|
+
# @since 1.3.0
|
217
|
+
# @api private
|
218
|
+
def optional?
|
219
|
+
@name[-1] == '?'
|
220
|
+
end
|
221
|
+
|
204
222
|
# Return the String representation of this TypeElement
|
205
223
|
#
|
206
224
|
# @since 1.1.0
|
@@ -8,7 +8,12 @@ module Taipo
|
|
8
8
|
|
9
9
|
# Initialize a new collection
|
10
10
|
#
|
11
|
-
# @
|
11
|
+
# @note The +components+ argument is two-dimensional array because the
|
12
|
+
# element returned by an enumerator for a collection can consist of
|
13
|
+
# multiple elements (eg. a Hash, where it consists of two elements).
|
14
|
+
#
|
15
|
+
# @param components [Array<Array<Taipo::TypeElement>>] the components that
|
16
|
+
# will make up the ChildType
|
12
17
|
#
|
13
18
|
# @since 1.0.0
|
14
19
|
# @api private
|
data/lib/taipo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: taipo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Camilleri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|