finitio 0.11.2 → 0.11.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/Gemfile.lock +1 -1
- data/lib/finitio/generation/proxy_type.rb +11 -0
- data/lib/finitio/generation.rb +1 -0
- data/lib/finitio/json_schema/hash_based_type.rb +1 -1
- data/lib/finitio/json_schema/proxy_type.rb +4 -1
- data/lib/finitio/support/compilation.rb +0 -4
- data/lib/finitio/support/proxy_resolver.rb +52 -0
- data/lib/finitio/support.rb +1 -0
- data/lib/finitio/syntax.rb +4 -4
- data/lib/finitio/system.rb +5 -16
- data/lib/finitio/type/high_order_type.rb +3 -1
- data/lib/finitio/type/proxy_type.rb +19 -1
- data/lib/finitio/type.rb +4 -2
- data/lib/finitio/version.rb +1 -1
- data/spec/inference/test_inference.rb +1 -1
- data/spec/json_schema/test_recursive_type.rb +38 -0
- data/spec/regression/test_dress_on_recursive_type.rb +53 -0
- data/spec/regression/test_name_of_generic_types.rb +18 -0
- data/spec/syntax/test_compile.rb +19 -1
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29fd883abee1e98b436a1c8aa80ee32ffc9740dc
|
4
|
+
data.tar.gz: 9aa135c687855dbdfb6a52e245d21c3488ef0128
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0af6653c37bc1fdb2e5aeef7f0d43e70f92d967658219b638c58a8039b975460f64ab80339d7d727aed716175cc722614973e387c5720315868bd6b8a6d1fc7c
|
7
|
+
data.tar.gz: ef96c4bd3a7f4910b83acab224940afe7a1885be98eeddf5ce8542c0037d0c702da98e372f55a42638cb7cef3cfbf9394dd8c0d162daace35c6731e86083c061
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# 0.11.4 - 2023/01/06
|
2
|
+
|
3
|
+
* The proxy resolution is fixed and clarified. When compiling
|
4
|
+
a system, all proxies are actually replaced by their actual
|
5
|
+
Type instance. Only recursive types still keep ProxyType
|
6
|
+
instances (as sentinels) ; they are bound to their target
|
7
|
+
type and delete dress and include? to them.
|
8
|
+
|
9
|
+
Given that ProxyType is a sentinel on recursive types, calls
|
10
|
+
to generate_data and to_json_schema are not delegated to the
|
11
|
+
target type, to avoid infinite recursions.
|
12
|
+
|
13
|
+
* Generated names of instantiated high order types are better
|
14
|
+
(e.g. Collection<String>).
|
15
|
+
|
16
|
+
# 0.11.3 - 2023/01/06
|
17
|
+
|
18
|
+
* Fix json_schema generation on unresolved ProxyTypes. We use
|
19
|
+
"object" by default, waiting for a better support for recursive
|
20
|
+
types.
|
21
|
+
|
1
22
|
# 0.11.2 - 2023/01/06
|
2
23
|
|
3
24
|
* Fix json_schema generation on builtin_type NilClass. "null"
|
data/Gemfile.lock
CHANGED
data/lib/finitio/generation.rb
CHANGED
@@ -7,7 +7,7 @@ module Finitio
|
|
7
7
|
}
|
8
8
|
unless heading.empty?
|
9
9
|
base[:properties] = heading.inject({}){|ps,a|
|
10
|
-
|
10
|
+
ps.merge(a.name => a.type.to_json_schema(*args, &bl))
|
11
11
|
}
|
12
12
|
end
|
13
13
|
unless (reqs = heading.select{|a| a.required? }).empty?
|
@@ -2,7 +2,10 @@ module Finitio
|
|
2
2
|
class ProxyType
|
3
3
|
|
4
4
|
def to_json_schema(*args, &bl)
|
5
|
-
|
5
|
+
# ProxyType is supposed to be used only for recursive types.
|
6
|
+
# We don't have support for references yet, so let just
|
7
|
+
# generate an object here in the mean time.
|
8
|
+
{ type: "object" }
|
6
9
|
end
|
7
10
|
|
8
11
|
end # module ProxyType
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Finitio
|
2
|
+
# Part of the compilation schema, this proxy resolver replaces
|
3
|
+
# proxies by their real Type instance.
|
4
|
+
#
|
5
|
+
# Given that Finitio can support recursive types, we do this in
|
6
|
+
# two passes:
|
7
|
+
# 1. Replace proxy types by rewrite (see Type#resolve_proxies)
|
8
|
+
# in a depth first search.
|
9
|
+
# 2. If a loop is found, recreate a late ProxyType, that is then
|
10
|
+
# bound later by mutation.
|
11
|
+
#
|
12
|
+
# So ProxyType may still be present in the type chain, but will
|
13
|
+
# only correspond to recursive types.
|
14
|
+
class ProxyResolver
|
15
|
+
def resolve!(system)
|
16
|
+
@system = system
|
17
|
+
@built = {}
|
18
|
+
@building = {}
|
19
|
+
@late_proxies = []
|
20
|
+
system.types.each_key do |name|
|
21
|
+
fetch(name)
|
22
|
+
end
|
23
|
+
@late_proxies.each do |proxy|
|
24
|
+
proxy.bind!(self)
|
25
|
+
end
|
26
|
+
system.dup(@built)
|
27
|
+
end
|
28
|
+
|
29
|
+
def fetch(name, &bl)
|
30
|
+
@built[name] || build_it(name) || import_it(name, &bl)
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_it(name)
|
34
|
+
if under_build = @building[name]
|
35
|
+
proxy = ProxyType.new(name)
|
36
|
+
@late_proxies << proxy
|
37
|
+
proxy
|
38
|
+
else
|
39
|
+
return nil unless type = @system.fetch(name, false){ nil }
|
40
|
+
|
41
|
+
@building[name] = type
|
42
|
+
@built[name] = type.resolve_proxies(self)
|
43
|
+
@building[name] = nil
|
44
|
+
@built[name]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def import_it(name, &bl)
|
49
|
+
@system.fetch_on_imports(name, &bl)
|
50
|
+
end
|
51
|
+
end # class ProxyResolver
|
52
|
+
end # module Finitio
|
data/lib/finitio/support.rb
CHANGED
data/lib/finitio/syntax.rb
CHANGED
@@ -21,18 +21,18 @@ module Finitio
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def self.ast(source)
|
24
|
-
parse(source, root:
|
24
|
+
parse(source, root: 'system').to_ast
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.compile(source, cpl = nil)
|
28
28
|
cpl = Compilation.coerce(cpl, source)
|
29
|
-
parse(source, root:
|
30
|
-
cpl.
|
29
|
+
parse(source, root: 'system').compile(cpl)
|
30
|
+
ProxyResolver.new.resolve!(cpl.system)
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.compile_type(source, cpl = nil)
|
34
34
|
cpl = Compilation.coerce(cpl, source)
|
35
|
-
parse(source, root:
|
35
|
+
parse(source, root: 'type').compile(cpl)
|
36
36
|
end
|
37
37
|
|
38
38
|
end # module Syntax
|
data/lib/finitio/system.rb
CHANGED
@@ -50,24 +50,23 @@ module Finitio
|
|
50
50
|
def fetch(name, with_imports = true, &bl)
|
51
51
|
if with_imports
|
52
52
|
@types.fetch(name) do
|
53
|
-
|
53
|
+
fetch_on_imports(name, &bl)
|
54
54
|
end
|
55
55
|
else
|
56
56
|
@types.fetch(name, &bl)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
60
|
+
def fetch_on_imports(name, imports = @imports, &bl)
|
61
61
|
if imports.empty?
|
62
62
|
raise KeyError, %Q{key not found: "#{name}"} unless bl
|
63
63
|
bl.call(name)
|
64
64
|
else
|
65
65
|
imports.first.fetch(name, false) do
|
66
|
-
|
66
|
+
fetch_on_imports(name, imports[1..-1], &bl)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
70
|
-
private :_fetch
|
71
70
|
|
72
71
|
def factory
|
73
72
|
@factory ||= TypeFactory.new
|
@@ -89,22 +88,12 @@ module Finitio
|
|
89
88
|
Syntax.compile(source, self.dup)
|
90
89
|
end
|
91
90
|
|
92
|
-
def resolve_proxies(recurse = true)
|
93
|
-
rebuilt = {}
|
94
|
-
scope = FetchScope.new(self, rebuilt)
|
95
|
-
types.each_with_object(rebuilt) do |(name,type),memo|
|
96
|
-
rebuilt[name] = type.resolve_proxies(scope)
|
97
|
-
end
|
98
|
-
resolved = System.new(rebuilt, imports)
|
99
|
-
recurse ? resolved.resolve_proxies(false) : resolved
|
100
|
-
end
|
101
|
-
|
102
91
|
def inspect
|
103
92
|
@types.each_pair.map{|k,v| "#{k} = #{v}" }.join("\n")
|
104
93
|
end
|
105
94
|
|
106
|
-
def dup
|
107
|
-
System.new(
|
95
|
+
def dup(types = @types.dup, imports = @imports.dup)
|
96
|
+
System.new(types, imports)
|
108
97
|
end
|
109
98
|
|
110
99
|
def check_and_warn(logger = nil)
|
@@ -28,7 +28,9 @@ module Finitio
|
|
28
28
|
|
29
29
|
def instantiate(compilation, sub_types)
|
30
30
|
overrides = Hash[vars.zip(sub_types)]
|
31
|
-
defn.resolve_proxies(compilation.with_scope(overrides))
|
31
|
+
defn.resolve_proxies(compilation.with_scope(overrides)).dup.tap{|x|
|
32
|
+
x.send(:name=, "#{name}<#{overrides.values.join(',')}>", true)
|
33
|
+
}
|
32
34
|
end
|
33
35
|
|
34
36
|
def unconstrained
|
@@ -15,8 +15,26 @@ module Finitio
|
|
15
15
|
"_#{target_name}_"
|
16
16
|
end
|
17
17
|
|
18
|
+
def include?(*args, &bl)
|
19
|
+
raise Error, "Proxy not resolved: #{target_name}" unless @target
|
20
|
+
|
21
|
+
@target.include?(*args, &bl)
|
22
|
+
end
|
23
|
+
|
24
|
+
def dress(*args, &bl)
|
25
|
+
raise Error, "Proxy not resolved: #{target_name}" unless @target
|
26
|
+
|
27
|
+
@target.dress(*args, &bl)
|
28
|
+
end
|
29
|
+
|
30
|
+
def bind!(system)
|
31
|
+
@target = system.fetch(target_name) {
|
32
|
+
raise Error, "No such type `#{target_name}` in #{system}"
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
18
36
|
def resolve_proxies(system)
|
19
|
-
system.fetch(target_name){
|
37
|
+
system.fetch(target_name) {
|
20
38
|
raise Error, "No such type `#{target_name}` in #{system}"
|
21
39
|
}
|
22
40
|
end
|
data/lib/finitio/type.rb
CHANGED
@@ -32,8 +32,10 @@ module Finitio
|
|
32
32
|
@name || default_name
|
33
33
|
end
|
34
34
|
|
35
|
-
def name=(n)
|
36
|
-
|
35
|
+
def name=(n, force = false)
|
36
|
+
if !@name.nil? && !force
|
37
|
+
raise Error, "Name already set to `#{@name}` on #{self.class}"
|
38
|
+
end
|
37
39
|
@name = n
|
38
40
|
end
|
39
41
|
|
data/lib/finitio/version.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Finitio
|
3
|
+
module JsonSchema
|
4
|
+
describe "A recursive type" do
|
5
|
+
|
6
|
+
let(:system){
|
7
|
+
::Finitio.system <<-FIO
|
8
|
+
Tree = {
|
9
|
+
children : [Tree]
|
10
|
+
}
|
11
|
+
FIO
|
12
|
+
}
|
13
|
+
|
14
|
+
let(:type) {
|
15
|
+
system['Tree']
|
16
|
+
}
|
17
|
+
|
18
|
+
it 'works as expected' do
|
19
|
+
expect(type.to_json_schema).to eql({
|
20
|
+
type: "object",
|
21
|
+
properties: {
|
22
|
+
children: {
|
23
|
+
type: "array",
|
24
|
+
items: {
|
25
|
+
type: "object"
|
26
|
+
}
|
27
|
+
}
|
28
|
+
},
|
29
|
+
required: [
|
30
|
+
:children
|
31
|
+
],
|
32
|
+
additionalProperties: false
|
33
|
+
})
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Dress on a recursive type" do
|
4
|
+
let(:schema){
|
5
|
+
Finitio.system <<~F
|
6
|
+
Tree = {
|
7
|
+
children: [Tree]
|
8
|
+
}
|
9
|
+
Tree
|
10
|
+
F
|
11
|
+
}
|
12
|
+
|
13
|
+
it 'works on an empty tree' do
|
14
|
+
expect(->(){
|
15
|
+
schema.dress({children: []})
|
16
|
+
}).not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'works on a non empty tree' do
|
20
|
+
expect(->(){
|
21
|
+
schema.dress({
|
22
|
+
children: [{
|
23
|
+
children: [{
|
24
|
+
children: [{
|
25
|
+
children: []
|
26
|
+
}]
|
27
|
+
}]
|
28
|
+
}]
|
29
|
+
})
|
30
|
+
}).not_to raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'detects deep error' do
|
34
|
+
expect(->(){
|
35
|
+
schema.dress({
|
36
|
+
children: [{
|
37
|
+
children: [{
|
38
|
+
children: [{
|
39
|
+
children: [{
|
40
|
+
children: [{
|
41
|
+
children: [{
|
42
|
+
unrecognized: true,
|
43
|
+
children: []
|
44
|
+
}]
|
45
|
+
}]
|
46
|
+
}]
|
47
|
+
}]
|
48
|
+
}]
|
49
|
+
}]
|
50
|
+
})
|
51
|
+
}).to raise_error(Finitio::Error)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "The types of generics definitions" do
|
4
|
+
describe "When the extra map to a type" do
|
5
|
+
let(:schema){
|
6
|
+
Finitio.system <<~F
|
7
|
+
Collection<T> = [T]
|
8
|
+
|
9
|
+
String = .String
|
10
|
+
Collection<String>
|
11
|
+
F
|
12
|
+
}
|
13
|
+
|
14
|
+
it 'works' do
|
15
|
+
expect(schema['Main'].target.name).to eql("Collection<String>")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/syntax/test_compile.rb
CHANGED
@@ -77,6 +77,24 @@ module Finitio
|
|
77
77
|
end
|
78
78
|
|
79
79
|
context 'with AD types' do
|
80
|
+
let(:source){
|
81
|
+
<<-EOF.strip
|
82
|
+
Int = .Integer
|
83
|
+
Byte = Int(i | i>0)
|
84
|
+
Color = .Color <rgb> { r: Byte, g: Byte, b: Byte }
|
85
|
+
Colors = [Color]
|
86
|
+
EOF
|
87
|
+
}
|
88
|
+
|
89
|
+
it{ should be_a(System) }
|
90
|
+
|
91
|
+
it 'should work fine' do
|
92
|
+
got = subject['Colors'].dress([{ r: 10, g: 15, b: 20 }])
|
93
|
+
expect(got.first).to be_a(Color)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'with AD types that make forward references' do
|
80
98
|
let(:source){
|
81
99
|
<<-EOF.strip
|
82
100
|
Colors = [Color]
|
@@ -88,7 +106,7 @@ module Finitio
|
|
88
106
|
|
89
107
|
it{ should be_a(System) }
|
90
108
|
|
91
|
-
it 'should work
|
109
|
+
it 'should work fine' do
|
92
110
|
got = subject['Colors'].dress([{ r: 10, g: 15, b: 20 }])
|
93
111
|
expect(got.first).to be_a(Color)
|
94
112
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: finitio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01-
|
11
|
+
date: 2023-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: citrus
|
@@ -163,6 +163,7 @@ files:
|
|
163
163
|
- lib/finitio/generation/heuristic.rb
|
164
164
|
- lib/finitio/generation/heuristic/constant.rb
|
165
165
|
- lib/finitio/generation/heuristic/random.rb
|
166
|
+
- lib/finitio/generation/proxy_type.rb
|
166
167
|
- lib/finitio/generation/rel_based_type.rb
|
167
168
|
- lib/finitio/generation/seq_type.rb
|
168
169
|
- lib/finitio/generation/set_type.rb
|
@@ -193,6 +194,7 @@ files:
|
|
193
194
|
- lib/finitio/support/heading.rb
|
194
195
|
- lib/finitio/support/metadata.rb
|
195
196
|
- lib/finitio/support/proc_with_code.rb
|
197
|
+
- lib/finitio/support/proxy_resolver.rb
|
196
198
|
- lib/finitio/support/type_factory.rb
|
197
199
|
- lib/finitio/syntax.rb
|
198
200
|
- lib/finitio/syntax/definitions.rb
|
@@ -309,6 +311,7 @@ files:
|
|
309
311
|
- spec/json_schema/test_builtin_type.rb
|
310
312
|
- spec/json_schema/test_multi_relation_type.rb
|
311
313
|
- spec/json_schema/test_multi_tuple_type.rb
|
314
|
+
- spec/json_schema/test_recursive_type.rb
|
312
315
|
- spec/json_schema/test_relation_type.rb
|
313
316
|
- spec/json_schema/test_seq_type.rb
|
314
317
|
- spec/json_schema/test_set_type.rb
|
@@ -316,7 +319,9 @@ files:
|
|
316
319
|
- spec/json_schema/test_sub_type.rb
|
317
320
|
- spec/json_schema/test_tuple_type.rb
|
318
321
|
- spec/json_schema/test_union_type.rb
|
322
|
+
- spec/regression/test_dress_on_recursive_type.rb
|
319
323
|
- spec/regression/test_heading_extra_are_proxy_resolved.rb
|
324
|
+
- spec/regression/test_name_of_generic_types.rb
|
320
325
|
- spec/spec_helper.rb
|
321
326
|
- spec/support/test_compare_attrs.rb
|
322
327
|
- spec/support/test_proc_with_code.rb
|
@@ -487,6 +492,8 @@ signing_key:
|
|
487
492
|
specification_version: 4
|
488
493
|
summary: Finitio - in Ruby
|
489
494
|
test_files:
|
495
|
+
- spec/regression/test_dress_on_recursive_type.rb
|
496
|
+
- spec/regression/test_name_of_generic_types.rb
|
490
497
|
- spec/regression/test_heading_extra_are_proxy_resolved.rb
|
491
498
|
- spec/test_finitio.rb
|
492
499
|
- spec/constraint/test_named.rb
|
@@ -616,6 +623,7 @@ test_files:
|
|
616
623
|
- spec/json_schema/test_ad_type.rb
|
617
624
|
- spec/json_schema/test_builtin_type.rb
|
618
625
|
- spec/json_schema/test_multi_relation_type.rb
|
626
|
+
- spec/json_schema/test_recursive_type.rb
|
619
627
|
- spec/json_schema/test_sub_type.rb
|
620
628
|
- spec/json_schema/test_any_type.rb
|
621
629
|
- spec/json_schema/test_seq_type.rb
|