dsl_maker 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fd8b809906f6bde7d8b1839095dc2ad018148190
4
- data.tar.gz: 13708d81d5f96de3f5744736c77f4b55ef2d5748
3
+ metadata.gz: 0338de58f7a2ecf13d08d203c4682bde172292f5
4
+ data.tar.gz: cc00e4a818b4aeb8b84841874878cd0851611703
5
5
  SHA512:
6
- metadata.gz: d0c2f6464bc5d08693a7298dae3074c9f89f00c9f2959bb1366b86a5cfdf211bc6fc779c045cb111fd04f0e0e7aff1aa8304ccd895d084fa32119e4fdba7c951
7
- data.tar.gz: c9ecc30fba1b36b6c6aac878de49a6191df39180ef05dd96996a411e82c5c52e44ef202254ba08736755e95fe9d8df3fba94ad512adc51ddc6d139d96f1a987a
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 use within `generate_dsl()`:
405
+ There are four pre-defined standard type coercions available for `generate_dsl()`:
406
406
 
407
- * Any - This takes whatever you give it and returns it back.
408
- * String - This takes whatever you give it and returns the string within it.
409
- * Integer - This takes whatever you give it and returns the integer within it.
410
- * Boolean - This takes whatever you give it and returns the truthiness of it.
411
- * `generate_dsl()` - This descends into another level of DSL.
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 above.
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] = ->(klass, name, 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
- @@types[type].call(klass, name, type)
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
 
@@ -1,6 +1,6 @@
1
1
  module DSL
2
2
  class Maker
3
3
  # The current version of this library
4
- VERSION = '0.0.8'
4
+ VERSION = '0.0.9'
5
5
  end
6
6
  end
@@ -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
@@ -40,6 +40,7 @@ module Structs
40
40
 
41
41
  $toppings = [:cheese, :pepperoni, :bacon, :sauce]
42
42
  Pizza = Struct.new(*$toppings)
43
+ Cheese = Struct.new(:type, :color)
43
44
 
44
45
  Color = Struct.new(:name)
45
46
  Fruit = Struct.new(:name, :color)
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.8
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-07 00:00:00.000000000 Z
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