dsl_maker 0.1.0 → 0.1.1
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/lib/dsl/maker.rb +55 -37
- data/lib/dsl/maker/version.rb +1 -1
- data/spec/error_spec.rb +29 -17
- data/spec/helper_spec.rb +67 -43
- 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: ee345a0ba8d01c3d91f40755ba0c18ac527c57eb
|
4
|
+
data.tar.gz: 515dae62c2f621d2ae8c12df517231d209e460a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0983a84dbed2c14f98b7f1d8d2ce6c76bfe59a24f4c74c604f52e8877e830286523de6e4cf3f7747d354e313235689e84dd1fb1bebdb2f3472645740b3217b97
|
7
|
+
data.tar.gz: b59a9f5d5e9095e5fcddbdbbdc0df8a43488a3d9d93ab2a58dcf435f681dd1fff97c5a6ec415352464ad2c7703931b767d5b08e3c54c49bda4b5aef636e57d9e
|
data/Changes
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
Revision history for DSL::Maker (ordered by revision number).
|
2
2
|
|
3
|
+
0.1.1 Aug 24 2015
|
4
|
+
- add_helper() no longer pollutes DSL::Maker::Base
|
5
|
+
- Add remove_helper() and has_helper?()
|
6
|
+
- Rename is_dsl() to is_dsl?()
|
7
|
+
|
3
8
|
0.1.0 Aug 11 2015
|
4
9
|
BREAKING CHANGE:
|
5
10
|
- parse_dsl() and execute_dsl() now always return an array, even if there is
|
data/lib/dsl/maker.rb
CHANGED
@@ -89,7 +89,7 @@ class DSL::Maker
|
|
89
89
|
ArrayOf = Class.new do
|
90
90
|
def self.[](type)
|
91
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)
|
92
|
+
raise "Unknown type provided to ArrayOf" unless @@types.has_key?(type) || DSL::Maker.is_dsl?(type)
|
93
93
|
@@arrays[type] ||= ArrayType.new(type)
|
94
94
|
end
|
95
95
|
end
|
@@ -99,12 +99,9 @@ class DSL::Maker
|
|
99
99
|
|
100
100
|
# Parse the DSL provided in the parameter.
|
101
101
|
#
|
102
|
-
# @note If the DSL contains multiple entrypoints, then this will return an
|
103
|
-
# Array. This is desirable.
|
104
|
-
#
|
105
102
|
# @param dsl [String] The DSL to be parsed by this class.
|
106
103
|
#
|
107
|
-
# @return [
|
104
|
+
# @return [Array] Whatever is returned by the block defined in this class.
|
108
105
|
def self.parse_dsl(dsl=nil)
|
109
106
|
raise 'Must call add_entrypoint before parse_dsl' unless @klass
|
110
107
|
raise 'String required for parse_dsl' unless dsl.instance_of? String
|
@@ -114,12 +111,9 @@ class DSL::Maker
|
|
114
111
|
|
115
112
|
# Execute the DSL provided in the block.
|
116
113
|
#
|
117
|
-
# @note If the DSL contains multiple entrypoints, then this will return an
|
118
|
-
# Array. This is desirable.
|
119
|
-
#
|
120
114
|
# @param &block [Block] The DSL to be executed by this class.
|
121
115
|
#
|
122
|
-
# @return [
|
116
|
+
# @return [Array] Whatever is returned by the block defined in this class.
|
123
117
|
def self.execute_dsl(&block)
|
124
118
|
raise 'Must call add_entrypoint before execute_dsl' unless @klass
|
125
119
|
raise 'Block required for execute_dsl' unless block_given?
|
@@ -140,7 +134,7 @@ class DSL::Maker
|
|
140
134
|
# and ___set() available for your use. These are aliases to
|
141
135
|
# instance_variable_get and instance_variable_set, respectively. Please read the
|
142
136
|
# coercions provided for you in this source file as examples.
|
143
|
-
#
|
137
|
+
#
|
144
138
|
# @return nil
|
145
139
|
def self.add_type(type, &block)
|
146
140
|
raise "Block required for add_type" unless block_given?
|
@@ -166,7 +160,7 @@ class DSL::Maker
|
|
166
160
|
def self.generate_dsl(args={}, &defn_block)
|
167
161
|
raise 'Block required for generate_dsl' unless block_given?
|
168
162
|
|
169
|
-
dsl_class = Class.new(
|
163
|
+
dsl_class = Class.new(base_class) do
|
170
164
|
include DSL::Maker::Boolean
|
171
165
|
|
172
166
|
class << self
|
@@ -199,7 +193,7 @@ class DSL::Maker
|
|
199
193
|
# @param name [String] the name of the entrypoint
|
200
194
|
# @param args [Hash] the elements of the DSL block (passed to generate_dsl)
|
201
195
|
# @param defn_block [Proc] what is executed once the DSL block is parsed.
|
202
|
-
#
|
196
|
+
#
|
203
197
|
# @return [Class] The class that implements this level's DSL definition.
|
204
198
|
def self.add_entrypoint(name, args={}, &defn_block)
|
205
199
|
symname = name.to_sym
|
@@ -208,7 +202,7 @@ class DSL::Maker
|
|
208
202
|
raise "'#{name.to_s}' is already an entrypoint"
|
209
203
|
end
|
210
204
|
|
211
|
-
if is_dsl(args)
|
205
|
+
if is_dsl?(args)
|
212
206
|
dsl_class = args
|
213
207
|
else
|
214
208
|
# Without defn_block, there's no way to give back the result of the
|
@@ -218,7 +212,7 @@ class DSL::Maker
|
|
218
212
|
raise "Block required for add_entrypoint" unless block_given?
|
219
213
|
dsl_class = generate_dsl(args, &defn_block)
|
220
214
|
end
|
221
|
-
|
215
|
+
|
222
216
|
if @klass
|
223
217
|
build_dsl_element(@klass, symname, dsl_class)
|
224
218
|
else
|
@@ -241,7 +235,7 @@ class DSL::Maker
|
|
241
235
|
# This returns the DSL corresponding to the entrypoint's name.
|
242
236
|
#
|
243
237
|
# @param name [String] the name of the entrypoint
|
244
|
-
#
|
238
|
+
#
|
245
239
|
# @return [Class] The class that implements this name's DSL definition.
|
246
240
|
def self.entrypoint(name)
|
247
241
|
unless is_entrypoint(name)
|
@@ -257,22 +251,46 @@ class DSL::Maker
|
|
257
251
|
#
|
258
252
|
# @param name [String] the name of the helper
|
259
253
|
# @param &block [Block] The function to be executed when the helper is called.
|
260
|
-
#
|
254
|
+
#
|
261
255
|
# @return nil
|
262
256
|
def self.add_helper(name, &block)
|
263
257
|
raise "Block required for add_helper" unless block_given?
|
264
258
|
|
265
|
-
if
|
259
|
+
if has_helper? name
|
266
260
|
raise "'#{name.to_s}' is already a helper"
|
267
261
|
end
|
268
262
|
|
269
|
-
|
263
|
+
base_class.class_eval do
|
270
264
|
define_method(name.to_sym, &block)
|
271
265
|
end
|
272
266
|
|
273
267
|
return
|
274
268
|
end
|
275
269
|
|
270
|
+
# This removes a helper function that's been added with #add_helper
|
271
|
+
#
|
272
|
+
# @param name [String] the name of the helper
|
273
|
+
#
|
274
|
+
# @return nil
|
275
|
+
def self.remove_helper(name)
|
276
|
+
unless has_helper? name
|
277
|
+
raise "'#{name.to_s}' is not a helper"
|
278
|
+
end
|
279
|
+
|
280
|
+
base_class.class_eval do
|
281
|
+
remove_method(name.to_sym)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# This returns if the helper has been added with #add_helper
|
286
|
+
#
|
287
|
+
# @param name [String] the name of the helper
|
288
|
+
#
|
289
|
+
# @return Boolean
|
290
|
+
def self.has_helper?(name)
|
291
|
+
base_class.method_defined?(name.to_sym)
|
292
|
+
end
|
293
|
+
|
276
294
|
# This adds a verification that's executed after the DSL is finished parsing.
|
277
295
|
#
|
278
296
|
# The verification will be called with the value(s) returned by the entrypoint's
|
@@ -289,7 +307,7 @@ class DSL::Maker
|
|
289
307
|
#
|
290
308
|
# @param name [String] the name of the entrypoint to add a verification to
|
291
309
|
# @param &block [Block] The function to be executed when verifications execute
|
292
|
-
#
|
310
|
+
#
|
293
311
|
# @return nil
|
294
312
|
def self.add_verification(name, &block)
|
295
313
|
raise "Block required for add_verification" unless block_given?
|
@@ -332,7 +350,7 @@ class DSL::Maker
|
|
332
350
|
instance_exec('@' + name.to_s, *args, &@@types[type])
|
333
351
|
end
|
334
352
|
end
|
335
|
-
elsif is_dsl(type)
|
353
|
+
elsif is_dsl?(type)
|
336
354
|
as_attr = '@' + name.to_s
|
337
355
|
klass.class_eval do
|
338
356
|
define_method(name.to_sym) do |*args, &dsl_block|
|
@@ -374,7 +392,7 @@ class DSL::Maker
|
|
374
392
|
___set(as_attr, rv = []) unless rv
|
375
393
|
|
376
394
|
if dsl_block
|
377
|
-
# This code is copy-pasted from the is_dsl() section above. Figure out
|
395
|
+
# This code is copy-pasted from the is_dsl?() section above. Figure out
|
378
396
|
# how to hoist this code into something reusable. But, we don't need
|
379
397
|
# the parent_class section (do we?)
|
380
398
|
obj = type.base_type.new
|
@@ -419,13 +437,28 @@ class DSL::Maker
|
|
419
437
|
return @accumulator
|
420
438
|
end
|
421
439
|
|
422
|
-
def self.is_dsl(proto)
|
440
|
+
def self.is_dsl?(proto)
|
423
441
|
proto.is_a?(Class) && proto.ancestors.include?(DSL::Maker::Base)
|
424
442
|
end
|
425
443
|
|
426
444
|
def self.is_entrypoint(name)
|
427
445
|
@entrypoints && @entrypoints.has_key?(name.to_sym)
|
428
446
|
end
|
447
|
+
|
448
|
+
def self.base_class
|
449
|
+
# This is the only time we *know* that the :default helper doesn't exist yet.
|
450
|
+
unless @base_class
|
451
|
+
@base_class = Class.new(DSL::Maker::Base)
|
452
|
+
add_helper(:default) do |method_name, args, position=0|
|
453
|
+
method = method_name.to_sym
|
454
|
+
if args.length >= (position + 1) && !self.send(method)
|
455
|
+
self.send(method, args[position])
|
456
|
+
end
|
457
|
+
return
|
458
|
+
end
|
459
|
+
end
|
460
|
+
@base_class
|
461
|
+
end
|
429
462
|
end
|
430
463
|
|
431
464
|
# These are the default setups
|
@@ -447,18 +480,3 @@ DSL::Maker.add_type(DSL::Maker::Boolean) do |attr, *args|
|
|
447
480
|
# Ensure that the default nil also returns as false.
|
448
481
|
!!___get(attr)
|
449
482
|
end
|
450
|
-
|
451
|
-
# A helper method for handling defaults from args easily.
|
452
|
-
#
|
453
|
-
# @param method_name [String] The name of the attribute being defaulted.
|
454
|
-
# @param args [Array] The arguments provided to the block.
|
455
|
-
# @param position [Integer] The index in args to work with, default 0.
|
456
|
-
#
|
457
|
-
# @return nil
|
458
|
-
DSL::Maker.add_helper(:default) do |method_name, args, position=0|
|
459
|
-
method = method_name.to_sym
|
460
|
-
if args.length >= (position + 1) && !self.send(method)
|
461
|
-
self.send(method, args[position])
|
462
|
-
end
|
463
|
-
return
|
464
|
-
end
|
data/lib/dsl/maker/version.rb
CHANGED
data/spec/error_spec.rb
CHANGED
@@ -125,29 +125,41 @@ describe "DSL::Maker validation" do
|
|
125
125
|
end
|
126
126
|
|
127
127
|
describe "for helpers" do
|
128
|
-
|
129
|
-
|
128
|
+
context "#add_helper" do
|
129
|
+
it "rejects a helper without a block" do
|
130
|
+
dsl_class = Class.new(DSL::Maker)
|
130
131
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
132
|
+
expect {
|
133
|
+
dsl_class.add_helper(:x)
|
134
|
+
}.to raise_error('Block required for add_helper')
|
135
|
+
end
|
135
136
|
|
136
|
-
|
137
|
-
|
137
|
+
it "rejects the helper name default" do
|
138
|
+
dsl_class = Class.new(DSL::Maker)
|
138
139
|
|
139
|
-
|
140
|
-
|
141
|
-
|
140
|
+
expect {
|
141
|
+
dsl_class.add_helper(:default) {}
|
142
|
+
}.to raise_error("'default' is already a helper")
|
143
|
+
end
|
144
|
+
|
145
|
+
it "rejects a helper name already in use" do
|
146
|
+
dsl_class = Class.new(DSL::Maker)
|
147
|
+
dsl_class.add_helper(:x) {}
|
148
|
+
|
149
|
+
expect {
|
150
|
+
dsl_class.add_helper(:x) {}
|
151
|
+
}.to raise_error("'x' is already a helper")
|
152
|
+
end
|
142
153
|
end
|
143
154
|
|
144
|
-
|
145
|
-
|
146
|
-
|
155
|
+
context "#remove_helper" do
|
156
|
+
it "rejects a helper name not already in use" do
|
157
|
+
dsl_class = Class.new(DSL::Maker)
|
147
158
|
|
148
|
-
|
149
|
-
|
150
|
-
|
159
|
+
expect {
|
160
|
+
dsl_class.remove_helper(:x)
|
161
|
+
}.to raise_error("'x' is not a helper")
|
162
|
+
end
|
151
163
|
end
|
152
164
|
end
|
153
165
|
|
data/spec/helper_spec.rb
CHANGED
@@ -1,60 +1,84 @@
|
|
1
1
|
# This uses a DSL that also provides a set of useful helpers.
|
2
2
|
#
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
:
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
describe 'A DSL with helpers' do
|
4
|
+
context '#add_helper' do
|
5
|
+
it "can add a helper that's useful" do
|
6
|
+
dsl_class = Class.new(DSL::Maker) do
|
7
|
+
add_entrypoint(:car, {
|
8
|
+
:maker => String,
|
9
|
+
}) do
|
10
|
+
Structs::Car.new(maker)
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
add_helper(:transform) do |name|
|
14
|
+
name.upcase
|
15
|
+
end
|
14
16
|
end
|
17
|
+
|
18
|
+
car = dsl_class.parse_dsl("
|
19
|
+
car {
|
20
|
+
maker transform('Honda')
|
21
|
+
}
|
22
|
+
")[0]
|
23
|
+
expect(car).to be_instance_of(Structs::Car)
|
24
|
+
expect(car.maker).to eq('HONDA')
|
15
25
|
end
|
16
26
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
27
|
+
it 'adds the helper to every level' do
|
28
|
+
dsl_class = Class.new(DSL::Maker) do
|
29
|
+
add_entrypoint(:car, {
|
30
|
+
:maker => String,
|
31
|
+
:wheel => generate_dsl({
|
32
|
+
:maker => String,
|
33
|
+
}) do
|
34
|
+
Structs::Wheel.new(maker)
|
35
|
+
end
|
36
|
+
}) do
|
37
|
+
Structs::Car.new(maker, wheel)
|
38
|
+
end
|
39
|
+
|
40
|
+
add_helper(:transform) do |name|
|
41
|
+
name.upcase
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
car = dsl_class.parse_dsl("
|
46
|
+
car {
|
47
|
+
maker 'Honda'
|
48
|
+
wheel {
|
49
|
+
maker transform('goodyear')
|
50
|
+
}
|
51
|
+
}
|
52
|
+
")[0]
|
53
|
+
expect(car).to be_instance_of(Structs::Car)
|
54
|
+
expect(car.maker).to eq('Honda')
|
55
|
+
expect(car.wheel).to be_instance_of(Structs::Wheel)
|
56
|
+
expect(car.wheel.maker).to eq('GOODYEAR')
|
57
|
+
end
|
24
58
|
end
|
25
59
|
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
dsl_class = Class.new(DSL::Maker) do
|
31
|
-
add_entrypoint(:car, {
|
32
|
-
:maker => String,
|
33
|
-
:wheel => generate_dsl({
|
60
|
+
context '#remove_helper' do
|
61
|
+
it 'can remove a helper' do
|
62
|
+
dsl_class = Class.new(DSL::Maker) do
|
63
|
+
add_entrypoint(:car, {
|
34
64
|
:maker => String,
|
35
65
|
}) do
|
36
|
-
Structs::
|
66
|
+
Structs::Car.new(maker)
|
37
67
|
end
|
38
|
-
}) do
|
39
|
-
Structs::Car.new(maker, wheel)
|
40
|
-
end
|
41
68
|
|
42
|
-
|
43
|
-
name
|
69
|
+
remove_helper(:default)
|
70
|
+
add_helper(:default) do |name|
|
71
|
+
name.upcase
|
72
|
+
end
|
44
73
|
end
|
45
|
-
end
|
46
74
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
wheel {
|
51
|
-
maker transform2('goodyear')
|
75
|
+
car = dsl_class.parse_dsl("
|
76
|
+
car {
|
77
|
+
maker default('Honda')
|
52
78
|
}
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
expect(car.wheel).to be_instance_of(Structs::Wheel)
|
58
|
-
expect(car.wheel.maker).to eq('GOODYEAR')
|
79
|
+
")[0]
|
80
|
+
expect(car).to be_instance_of(Structs::Car)
|
81
|
+
expect(car.maker).to eq('HONDA')
|
82
|
+
end
|
59
83
|
end
|
60
84
|
end
|
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.1.
|
4
|
+
version: 0.1.1
|
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-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docile
|