dsl_maker 0.1.0 → 0.1.1

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: 99ee47867d6b31ded1c99a54a01aa793a61592f3
4
- data.tar.gz: 5e11770909897a850465398142d13ea52e533f54
3
+ metadata.gz: ee345a0ba8d01c3d91f40755ba0c18ac527c57eb
4
+ data.tar.gz: 515dae62c2f621d2ae8c12df517231d209e460a8
5
5
  SHA512:
6
- metadata.gz: 9106d1d87a86d23e4eccb86b39d4a972e413cf3ce1dd7c469f36889de039f4162494da84abc0a5247312f61e64ca2c1b5b33e5ac694e3428d8640771d8de6504
7
- data.tar.gz: 9e1084f369c61cc4029b90ff76a555f17203b3c52913d5aaca1168b93f7725d1b8f2696170b12047e12fb936a7dc24acb0cf8e2ad24688493249a3b17db03b7e
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 [Object] Whatever is returned by the block defined in this class.
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 [Object] Whatever is returned by &block
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(DSL::Maker::Base) do
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 DSL::Maker::Base.new.respond_to? name.to_sym
259
+ if has_helper? name
266
260
  raise "'#{name.to_s}' is already a helper"
267
261
  end
268
262
 
269
- DSL::Maker::Base.class_eval do
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
@@ -1,6 +1,6 @@
1
1
  module DSL
2
2
  class Maker
3
3
  # The current version of this library
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
6
6
  end
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
- it "rejects a helper without a block" do
129
- dsl_class = Class.new(DSL::Maker)
128
+ context "#add_helper" do
129
+ it "rejects a helper without a block" do
130
+ dsl_class = Class.new(DSL::Maker)
130
131
 
131
- expect {
132
- dsl_class.add_helper(:x)
133
- }.to raise_error('Block required for add_helper')
134
- end
132
+ expect {
133
+ dsl_class.add_helper(:x)
134
+ }.to raise_error('Block required for add_helper')
135
+ end
135
136
 
136
- it "rejects the helper name default" do
137
- dsl_class = Class.new(DSL::Maker)
137
+ it "rejects the helper name default" do
138
+ dsl_class = Class.new(DSL::Maker)
138
139
 
139
- expect {
140
- dsl_class.add_helper(:default) {}
141
- }.to raise_error("'default' is already a helper")
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
- it "rejects a helper name already in use" do
145
- dsl_class = Class.new(DSL::Maker)
146
- dsl_class.add_helper(:x) {}
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
- expect {
149
- dsl_class.add_helper(:x) {}
150
- }.to raise_error("'x' is already a helper")
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 "A DSL with helpers" do
4
- it "can add a helper that's useful" do
5
- dsl_class = Class.new(DSL::Maker) do
6
- add_entrypoint(:car, {
7
- :maker => String,
8
- }) do
9
- Structs::Car.new(maker)
10
- end
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
- add_helper(:transform) do |name|
13
- name.upcase
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
- car = dsl_class.parse_dsl("
18
- car {
19
- maker transform('Honda')
20
- }
21
- ")[0]
22
- expect(car).to be_instance_of(Structs::Car)
23
- expect(car.maker).to eq('HONDA')
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
- # TODO: There is a wart here. We cannot call add_helper() twice in our tests
27
- # for the same name even in different specs. The specs should be able to reset
28
- # the class, but I'm not sure how.
29
- it "adds the helper to every level" do
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::Wheel.new(maker)
66
+ Structs::Car.new(maker)
37
67
  end
38
- }) do
39
- Structs::Car.new(maker, wheel)
40
- end
41
68
 
42
- add_helper(:transform2) do |name|
43
- name.upcase
69
+ remove_helper(:default)
70
+ add_helper(:default) do |name|
71
+ name.upcase
72
+ end
44
73
  end
45
- end
46
74
 
47
- car = dsl_class.parse_dsl("
48
- car {
49
- maker 'Honda'
50
- wheel {
51
- maker transform2('goodyear')
75
+ car = dsl_class.parse_dsl("
76
+ car {
77
+ maker default('Honda')
52
78
  }
53
- }
54
- ")[0]
55
- expect(car).to be_instance_of(Structs::Car)
56
- expect(car.maker).to eq('Honda')
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.0
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 00:00:00.000000000 Z
11
+ date: 2015-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docile