dsl_maker 0.0.8 → 0.0.9
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/Changes +5 -0
- data/README.md +20 -7
- data/lib/dsl/maker.rb +80 -9
- data/lib/dsl/maker/version.rb +1 -1
- data/spec/alias_type_spec.rb +91 -0
- data/spec/array_type_spec.rb +135 -0
- data/spec/error_spec.rb +20 -0
- data/spec/spec_helper.rb +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0338de58f7a2ecf13d08d203c4682bde172292f5
|
4
|
+
data.tar.gz: cc00e4a818b4aeb8b84841874878cd0851611703
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b272b83ae0a2485dbe1890172fbf03ac7cf4885cfd97d21b853008f7cbd30c930b2f7734f1ec886c5d2924e46fc41bc1853bccec8223997e7f9af9bd45f8e0a
|
7
|
+
data.tar.gz: 1cf59abb5d74f12358e234dde90d072348b938e993ab0884487a0715215ab15a5909abc17b11b0954035e81fe32edd11d2ad872dbb17dbd8fdc8aeadcc94b16b
|
data/Changes
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
Revision history for DSL::Maker (ordered by revision number).
|
2
2
|
|
3
|
+
0.0.9 Aug 11 2015
|
4
|
+
- Added the ArrayOf[<type>] type to allow for arrays to concatenate properly.
|
5
|
+
- Added the AliasOf(<name>) type to allow for use of multiple names to refer to
|
6
|
+
the same thing.
|
7
|
+
|
3
8
|
0.0.8 Aug 07 2015
|
4
9
|
- Make sure to provide a unique value for each type name.
|
5
10
|
- Allow 'Object' to be used as an alias for 'Any'
|
data/README.md
CHANGED
@@ -402,15 +402,28 @@ were encountered.
|
|
402
402
|
|
403
403
|
### Type Coercions
|
404
404
|
|
405
|
-
There are four pre-defined type coercions for
|
405
|
+
There are four pre-defined standard type coercions available for `generate_dsl()`:
|
406
406
|
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
407
|
+
Standard coercions:
|
408
|
+
* Any - This takes whatever you give it and returns it back.
|
409
|
+
* String - This takes whatever you give it and returns the string within it.
|
410
|
+
* Integer - This takes whatever you give it and returns the integer within it.
|
411
|
+
* Boolean - This takes whatever you give it and returns the truthiness of it.
|
412
412
|
|
413
|
-
You can add additional type coercions using `add_type()` as described
|
413
|
+
You can add additional standard type coercions using `add_type()` as described
|
414
|
+
above.
|
415
|
+
|
416
|
+
There are also three special type coercions that are not creatable with
|
417
|
+
`add_type()` because they do special manipulations within DSL::Maker.
|
418
|
+
|
419
|
+
Special coercions:
|
420
|
+
* `generate_dsl()` - This descends into another level of DSL.
|
421
|
+
* ArrayOf[<type>] - This creates an array coerced as the <type>. Successive
|
422
|
+
invocations are concatenated. <type> can be a DSL.
|
423
|
+
* AliasOf(<name>) - this creates an additional name that is synonomous with
|
424
|
+
the <name> item. You can use either this name or <name>.
|
425
|
+
|
426
|
+
These are special-cased within `build_dsl_element()`.
|
414
427
|
|
415
428
|
### Helpers
|
416
429
|
|
data/lib/dsl/maker.rb
CHANGED
@@ -65,6 +65,38 @@ class DSL::Maker
|
|
65
65
|
Yes = On = True = true
|
66
66
|
No = Off = False = false
|
67
67
|
|
68
|
+
class Alias
|
69
|
+
attr_reader :real_name
|
70
|
+
def initialize(real_name)
|
71
|
+
@real_name = real_name
|
72
|
+
end
|
73
|
+
end
|
74
|
+
@@aliases = {}
|
75
|
+
def self.AliasOf(name)
|
76
|
+
@@aliases[name] ||= Alias.new(name)
|
77
|
+
end
|
78
|
+
def self.is_alias(type)
|
79
|
+
type.instance_of? Alias
|
80
|
+
end
|
81
|
+
|
82
|
+
class ArrayType
|
83
|
+
attr_reader :base_type
|
84
|
+
def initialize(base_type)
|
85
|
+
@base_type = base_type
|
86
|
+
end
|
87
|
+
end
|
88
|
+
@@arrays = {}
|
89
|
+
ArrayOf = Class.new do
|
90
|
+
def self.[](type)
|
91
|
+
raise "Cannot make an array of an alias" if DSL::Maker.is_alias(type)
|
92
|
+
raise "Unknown type provided to ArrayOf" unless @@types.has_key?(type) || DSL::Maker.is_dsl(type)
|
93
|
+
@@arrays[type] ||= ArrayType.new(type)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
def self.is_array(type)
|
97
|
+
type.instance_of? ArrayType
|
98
|
+
end
|
99
|
+
|
68
100
|
# Parse the DSL provided in the parameter.
|
69
101
|
#
|
70
102
|
# @note If the DSL contains multiple entrypoints, then this will return an
|
@@ -114,13 +146,7 @@ class DSL::Maker
|
|
114
146
|
raise "Block required for add_type" unless block_given?
|
115
147
|
raise "'#{type}' is already a type coercion" if @@types.has_key? type
|
116
148
|
|
117
|
-
@@types[type] =
|
118
|
-
klass.class_eval do
|
119
|
-
define_method(name.to_sym) do |*args|
|
120
|
-
instance_exec('@' + name.to_s, *args, &block)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
}
|
149
|
+
@@types[type] = block
|
124
150
|
|
125
151
|
return
|
126
152
|
end
|
@@ -290,6 +316,8 @@ class DSL::Maker
|
|
290
316
|
# * Integer - the integer value of whatever you give is returned.
|
291
317
|
# * Boolean - the truthiness of whatever you give is returned.
|
292
318
|
# * generate_dsl() - this represents a new level of the DSL.
|
319
|
+
# * AliasOf(<name>) - this aliases a name to another name.
|
320
|
+
# * ArrayOf[<type>] - this creates an array of the <type> coercion.
|
293
321
|
#
|
294
322
|
# @param klass [Class] The class representing this level in the DSL.
|
295
323
|
# @param name [String] The name of the element we're working on.
|
@@ -299,7 +327,11 @@ class DSL::Maker
|
|
299
327
|
# @return nil
|
300
328
|
def self.build_dsl_element(klass, name, type)
|
301
329
|
if @@types.has_key?(type)
|
302
|
-
|
330
|
+
klass.class_eval do
|
331
|
+
define_method(name.to_sym) do |*args|
|
332
|
+
instance_exec('@' + name.to_s, *args, &@@types[type])
|
333
|
+
end
|
334
|
+
end
|
303
335
|
elsif is_dsl(type)
|
304
336
|
as_attr = '@' + name.to_s
|
305
337
|
klass.class_eval do
|
@@ -329,6 +361,46 @@ class DSL::Maker
|
|
329
361
|
___get(as_attr)
|
330
362
|
end
|
331
363
|
end
|
364
|
+
elsif is_alias(type)
|
365
|
+
klass.class_eval do
|
366
|
+
alias_method name, type.real_name
|
367
|
+
end
|
368
|
+
elsif is_array(type)
|
369
|
+
as_attr = '@' + name.to_s
|
370
|
+
|
371
|
+
klass.class_eval do
|
372
|
+
define_method(name.to_sym) do |*args, &dsl_block|
|
373
|
+
rv = ___get(as_attr)
|
374
|
+
___set(as_attr, rv = []) unless rv
|
375
|
+
|
376
|
+
if dsl_block
|
377
|
+
# This code is copy-pasted from the is_dsl() section above. Figure out
|
378
|
+
# how to hoist this code into something reusable. But, we don't need
|
379
|
+
# the parent_class section (do we?)
|
380
|
+
obj = type.base_type.new
|
381
|
+
Docile.dsl_eval(obj, &dsl_block)
|
382
|
+
dsl_value = obj.__apply(*args)
|
383
|
+
|
384
|
+
if v = type.base_type.instance_variable_get(:@verifications)
|
385
|
+
v.each do |verify|
|
386
|
+
failure = verify.call(dsl_value)
|
387
|
+
raise failure if failure
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
rv.push(dsl_value)
|
392
|
+
elsif !args.empty?
|
393
|
+
rv.concat(
|
394
|
+
args.map do |item|
|
395
|
+
# Assumption: 10x_ will never be used as an attribute name.
|
396
|
+
klass.new.instance_exec('@__________', item, &@@types[type.base_type])
|
397
|
+
end
|
398
|
+
)
|
399
|
+
end
|
400
|
+
|
401
|
+
rv
|
402
|
+
end
|
403
|
+
end
|
332
404
|
else
|
333
405
|
raise "Unrecognized element type '#{type}'"
|
334
406
|
end
|
@@ -356,7 +428,6 @@ class DSL::Maker
|
|
356
428
|
|
357
429
|
def self.is_entrypoint(name)
|
358
430
|
@entrypoints && @entrypoints.has_key?(name.to_sym)
|
359
|
-
#@klass && @klass.new.respond_to?(name.to_sym)
|
360
431
|
end
|
361
432
|
end
|
362
433
|
|
data/lib/dsl/maker/version.rb
CHANGED
@@ -0,0 +1,91 @@
|
|
1
|
+
# This is to test the AliasOf(:name) type
|
2
|
+
|
3
|
+
describe "Packager DSL AliasOf" do
|
4
|
+
# This uses $toppings defined in spec/spec_helper.rb
|
5
|
+
def verify_pizza(pizza, values={})
|
6
|
+
expect(pizza).to be_instance_of(Structs::Pizza)
|
7
|
+
$toppings.each do |topping|
|
8
|
+
expect(pizza.send(topping)).to eq(values[topping])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "can alias a Boolean" do
|
13
|
+
dsl_class = Class.new(DSL::Maker) do
|
14
|
+
add_entrypoint(:pizza, {
|
15
|
+
:cheese => DSL::Maker::Boolean,
|
16
|
+
:cheeseyness => DSL::Maker::AliasOf(:cheese),
|
17
|
+
}) {
|
18
|
+
Structs::Pizza.new(cheeseyness)
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
pizza = dsl_class.execute_dsl {
|
23
|
+
pizza { cheese yes }
|
24
|
+
}
|
25
|
+
verify_pizza(pizza, :cheese => true)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can alias multiple times" do
|
29
|
+
dsl_class = Class.new(DSL::Maker) do
|
30
|
+
add_entrypoint(:pizza, {
|
31
|
+
:cheese => DSL::Maker::Boolean,
|
32
|
+
:cheeseyness => DSL::Maker::AliasOf(:cheese),
|
33
|
+
:fromage => DSL::Maker::AliasOf(:cheese),
|
34
|
+
}) {
|
35
|
+
Structs::Pizza.new(cheeseyness)
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
pizza = dsl_class.execute_dsl {
|
40
|
+
pizza { fromage yes }
|
41
|
+
}
|
42
|
+
verify_pizza(pizza, :cheese => true)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "can have many different aliases" do
|
46
|
+
dsl_class = Class.new(DSL::Maker) do
|
47
|
+
add_entrypoint(:pizza, {
|
48
|
+
:cheese => DSL::Maker::Boolean,
|
49
|
+
:fromage => DSL::Maker::AliasOf(:cheese),
|
50
|
+
:bacon => DSL::Maker::Boolean,
|
51
|
+
:panceta => DSL::Maker::AliasOf(:bacon),
|
52
|
+
}) {
|
53
|
+
Structs::Pizza.new(fromage, nil, panceta)
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
pizza = dsl_class.execute_dsl {
|
58
|
+
pizza {
|
59
|
+
cheese yes
|
60
|
+
bacon yes
|
61
|
+
}
|
62
|
+
}
|
63
|
+
verify_pizza(pizza, :cheese => true, :bacon => true)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "can alias a DSL" do
|
67
|
+
dsl_class = Class.new(DSL::Maker) do
|
68
|
+
add_entrypoint(:pizza, {
|
69
|
+
:cheese => generate_dsl({
|
70
|
+
:type => String,
|
71
|
+
:color => String,
|
72
|
+
}) do
|
73
|
+
Structs::Cheese.new(type, color)
|
74
|
+
end,
|
75
|
+
:cheeseyness => DSL::Maker::AliasOf(:cheese)
|
76
|
+
}) {
|
77
|
+
Structs::Pizza.new(cheeseyness)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
pizza = dsl_class.execute_dsl {
|
82
|
+
pizza {
|
83
|
+
cheese {
|
84
|
+
type 'mozzarrella'
|
85
|
+
color 'white'
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
verify_pizza(pizza, :cheese => Structs::Cheese.new('mozzarrella', 'white'))
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
describe "Packager DSL ArrayOf" do
|
2
|
+
# This uses $toppings defined in spec/spec_helper.rb
|
3
|
+
def verify_pizza(pizza, values={})
|
4
|
+
expect(pizza).to be_instance_of(Structs::Pizza)
|
5
|
+
$toppings.each do |topping|
|
6
|
+
expect(pizza.send(topping)).to eq(values[topping])
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can array a String" do
|
11
|
+
dsl_class = Class.new(DSL::Maker) do
|
12
|
+
add_entrypoint(:pizza, {
|
13
|
+
:cheeses => DSL::Maker::ArrayOf[String],
|
14
|
+
:cheese => DSL::Maker::AliasOf(:cheeses),
|
15
|
+
}) {
|
16
|
+
Structs::Pizza.new(cheeses)
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
pizza = dsl_class.execute_dsl {
|
21
|
+
pizza {
|
22
|
+
cheeses :cheddar
|
23
|
+
cheeses 'mozzarrella'
|
24
|
+
}
|
25
|
+
}
|
26
|
+
verify_pizza(pizza, :cheese => %w(cheddar mozzarrella))
|
27
|
+
|
28
|
+
pizza = dsl_class.execute_dsl {
|
29
|
+
pizza {
|
30
|
+
cheeses 'cheddar', 'mozzarrella'
|
31
|
+
}
|
32
|
+
}
|
33
|
+
verify_pizza(pizza, :cheese => %w(cheddar mozzarrella))
|
34
|
+
end
|
35
|
+
|
36
|
+
it "can array a DSL" do
|
37
|
+
dsl_class = Class.new(DSL::Maker) do
|
38
|
+
cheese_dsl = generate_dsl({
|
39
|
+
:type => String,
|
40
|
+
:color => String,
|
41
|
+
}) do
|
42
|
+
Structs::Cheese.new(type, color)
|
43
|
+
end
|
44
|
+
|
45
|
+
add_entrypoint(:pizza, {
|
46
|
+
:cheeses => DSL::Maker::ArrayOf[cheese_dsl],
|
47
|
+
:cheese => DSL::Maker::AliasOf(:cheeses),
|
48
|
+
}) {
|
49
|
+
Structs::Pizza.new(cheeses)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
pizza = dsl_class.execute_dsl {
|
54
|
+
pizza {
|
55
|
+
cheese {
|
56
|
+
type 'mozzarrella'
|
57
|
+
color 'white'
|
58
|
+
}
|
59
|
+
cheese {
|
60
|
+
type 'cheddar'
|
61
|
+
color 'orange'
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
verify_pizza(pizza, :cheese => [
|
66
|
+
Structs::Cheese.new('mozzarrella', 'white'),
|
67
|
+
Structs::Cheese.new('cheddar', 'orange'),
|
68
|
+
])
|
69
|
+
end
|
70
|
+
|
71
|
+
it "can array a DSL with verifications" do
|
72
|
+
dsl_class = Class.new(DSL::Maker) do
|
73
|
+
cheese_dsl = generate_dsl({
|
74
|
+
:type => String,
|
75
|
+
:color => String,
|
76
|
+
}) do
|
77
|
+
Structs::Cheese.new(type, color)
|
78
|
+
end
|
79
|
+
cheese_dsl.add_verification do |item|
|
80
|
+
return "Cheese must have a color" unless item.color
|
81
|
+
end
|
82
|
+
|
83
|
+
add_entrypoint(:pizza, {
|
84
|
+
:cheeses => DSL::Maker::ArrayOf[cheese_dsl],
|
85
|
+
:cheese => DSL::Maker::AliasOf(:cheeses),
|
86
|
+
}) {
|
87
|
+
Structs::Pizza.new(cheeses)
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
expect {
|
92
|
+
dsl_class.execute_dsl {
|
93
|
+
pizza {
|
94
|
+
cheese {
|
95
|
+
type 'mozzarrella'
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}.to raise_error("Cheese must have a color")
|
100
|
+
end
|
101
|
+
|
102
|
+
it "can array a DSL with arguments" do
|
103
|
+
dsl_class = Class.new(DSL::Maker) do
|
104
|
+
cheese_dsl = generate_dsl({
|
105
|
+
:type => String,
|
106
|
+
:color => String,
|
107
|
+
}) do |*args|
|
108
|
+
default(:type, args, 0)
|
109
|
+
Structs::Cheese.new(type, color)
|
110
|
+
end
|
111
|
+
|
112
|
+
add_entrypoint(:pizza, {
|
113
|
+
:cheeses => DSL::Maker::ArrayOf[cheese_dsl],
|
114
|
+
:cheese => DSL::Maker::AliasOf(:cheeses),
|
115
|
+
}) {
|
116
|
+
Structs::Pizza.new(cheeses)
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
pizza = dsl_class.execute_dsl {
|
121
|
+
pizza {
|
122
|
+
cheese 'mozzarrella' do
|
123
|
+
color 'white'
|
124
|
+
end
|
125
|
+
cheese 'cheddar' do
|
126
|
+
color 'orange'
|
127
|
+
end
|
128
|
+
}
|
129
|
+
}
|
130
|
+
verify_pizza(pizza, :cheese => [
|
131
|
+
Structs::Cheese.new('mozzarrella', 'white'),
|
132
|
+
Structs::Cheese.new('cheddar', 'orange'),
|
133
|
+
])
|
134
|
+
end
|
135
|
+
end
|
data/spec/error_spec.rb
CHANGED
@@ -167,5 +167,25 @@ describe "DSL::Maker validation" do
|
|
167
167
|
dsl_class.add_type(String) {}
|
168
168
|
}.to raise_error("'String' is already a type coercion")
|
169
169
|
end
|
170
|
+
|
171
|
+
it "rejects an ArrayOf[type] if type isn't known" do
|
172
|
+
expect {
|
173
|
+
Class.new(DSL::Maker) do
|
174
|
+
generate_dsl({
|
175
|
+
:foo => DSL::Maker::ArrayOf[:does_not_exist]
|
176
|
+
}) {}
|
177
|
+
end
|
178
|
+
}.to raise_error("Unknown type provided to ArrayOf")
|
179
|
+
end
|
180
|
+
|
181
|
+
it "rejects an ArrayOf[type] if type is an alias" do
|
182
|
+
expect {
|
183
|
+
Class.new(DSL::Maker) do
|
184
|
+
generate_dsl({
|
185
|
+
:foo => DSL::Maker::ArrayOf[DSL::Maker::AliasOf(:foo)]
|
186
|
+
}) {}
|
187
|
+
end
|
188
|
+
}.to raise_error("Cannot make an array of an alias")
|
189
|
+
end
|
170
190
|
end
|
171
191
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dsl_maker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Kinyon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docile
|
@@ -154,7 +154,9 @@ files:
|
|
154
154
|
- lib/dsl/maker.rb
|
155
155
|
- lib/dsl/maker/version.rb
|
156
156
|
- on_what.rb
|
157
|
+
- spec/alias_type_spec.rb
|
157
158
|
- spec/args_spec.rb
|
159
|
+
- spec/array_type_spec.rb
|
158
160
|
- spec/class_as_subdsl_spec.rb
|
159
161
|
- spec/error_spec.rb
|
160
162
|
- spec/helper_spec.rb
|