dsl_compose 1.0.0 → 1.2.0
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/CHANGELOG.md +20 -0
- data/README.md +300 -3
- data/lib/dsl_compose/composer.rb +74 -0
- data/lib/dsl_compose/dsl/arguments/argument/equal_to_validation.rb +25 -0
- data/lib/dsl_compose/dsl/arguments/argument/format_validation.rb +25 -0
- data/lib/dsl_compose/dsl/arguments/argument/greater_than_or_equal_to_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/greater_than_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/in_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/interpreter.rb +86 -0
- data/lib/dsl_compose/dsl/arguments/argument/length_validation.rb +42 -0
- data/lib/dsl_compose/dsl/arguments/argument/less_than_or_equal_to_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/less_than_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/not_in_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument.rb +299 -0
- data/lib/dsl_compose/dsl/arguments.rb +113 -0
- data/lib/dsl_compose/dsl/dsl_method/interpreter.rb +57 -0
- data/lib/dsl_compose/dsl/dsl_method.rb +143 -0
- data/lib/dsl_compose/dsl/interpreter.rb +72 -0
- data/lib/dsl_compose/dsl.rb +152 -0
- data/lib/dsl_compose/dsls.rb +80 -0
- data/lib/dsl_compose/interpreter/execution/arguments.rb +145 -0
- data/lib/dsl_compose/interpreter/execution/method_calls/method_call.rb +53 -0
- data/lib/dsl_compose/interpreter/execution/method_calls.rb +25 -0
- data/lib/dsl_compose/interpreter/execution.rb +64 -0
- data/lib/dsl_compose/interpreter.rb +50 -0
- data/lib/dsl_compose/version.rb +2 -2
- data/lib/dsl_compose.rb +35 -4
- metadata +26 -3
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class LengthValidation
|
8
|
+
class ValidationFailedError < StandardError
|
9
|
+
def message
|
10
|
+
"The argument is invalid"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize maximum: nil, minimum: nil, is: nil
|
15
|
+
@maximum = maximum
|
16
|
+
@minimum = minimum
|
17
|
+
@is = is
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate! value
|
21
|
+
maximum = @maximum
|
22
|
+
unless maximum.nil?
|
23
|
+
raise ValidationFailedError if value.length > maximum
|
24
|
+
end
|
25
|
+
|
26
|
+
minimum = @minimum
|
27
|
+
unless minimum.nil?
|
28
|
+
raise ValidationFailedError if value.length < minimum
|
29
|
+
end
|
30
|
+
|
31
|
+
is = @is
|
32
|
+
unless is.nil?
|
33
|
+
raise ValidationFailedError if value.length != is
|
34
|
+
end
|
35
|
+
|
36
|
+
true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class LessThanOrEqualToValidation
|
8
|
+
class InvalidValueError < StandardError
|
9
|
+
def message
|
10
|
+
"The value provided to validate_greater_than must be a number"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ValidationFailedError < StandardError
|
15
|
+
def message
|
16
|
+
"The argument is invalid"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize value
|
21
|
+
unless value.is_a?(Numeric)
|
22
|
+
raise InvalidValueError
|
23
|
+
end
|
24
|
+
|
25
|
+
@value = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate! value
|
29
|
+
raise ValidationFailedError unless value <= @value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class LessThanValidation
|
8
|
+
class InvalidValueError < StandardError
|
9
|
+
def message
|
10
|
+
"The value provided to validate_greater_than must be a number"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ValidationFailedError < StandardError
|
15
|
+
def message
|
16
|
+
"The argument is invalid"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize value
|
21
|
+
unless value.is_a?(Numeric)
|
22
|
+
raise InvalidValueError
|
23
|
+
end
|
24
|
+
|
25
|
+
@value = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate! value
|
29
|
+
raise ValidationFailedError unless value < @value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class NotInValidation
|
8
|
+
class InvalidValueError < StandardError
|
9
|
+
def message
|
10
|
+
"The value provided to validate_greater_than must be a number"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ValidationFailedError < StandardError
|
15
|
+
def message
|
16
|
+
"The argument is invalid"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize values
|
21
|
+
unless values.is_a?(Array)
|
22
|
+
raise InvalidValueError
|
23
|
+
end
|
24
|
+
|
25
|
+
@values = values
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate! value
|
29
|
+
raise ValidationFailedError if @values.include?(value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,299 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class ValidationIncompatibleError < StandardError
|
8
|
+
def message
|
9
|
+
"The validation is not compatible with this argument type"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ValidationAlreadyExistsError < StandardError
|
14
|
+
def message
|
15
|
+
"This validation has already been applied to this method option."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class InvalidTypeError < StandardError
|
20
|
+
def message
|
21
|
+
"Argument type must be one of :integer, :boolean, :float, :string or :symbol"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class InvalidNameError < StandardError
|
26
|
+
def message
|
27
|
+
"The option name is invalid, it must be of type symbol."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class InvalidDescriptionError < StandardError
|
32
|
+
def message
|
33
|
+
"The option description is invalid, it must be of type string and have length greater than 0."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class DescriptionAlreadyExistsError < StandardError
|
38
|
+
def message
|
39
|
+
"The description has already been set"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# The name of this Argument.
|
44
|
+
attr_reader :name
|
45
|
+
# An arguments type. This determines what kind of value can be passed when calling the
|
46
|
+
# associated DSLMethod.
|
47
|
+
# `type` should be set to either :integer, :boolean, :float, :string or :symbol
|
48
|
+
attr_reader :type
|
49
|
+
# if required, then this Argument must be provided when calling its associated DSLMethod.
|
50
|
+
attr_reader :required
|
51
|
+
# An otional description of this Attribute, if provided then it must be a string.
|
52
|
+
# The description accepts markdown and is used when generating documentation.
|
53
|
+
attr_reader :description
|
54
|
+
# Optional validations that have been applied to this Argument. When the DSL is used
|
55
|
+
# each of these validations will be checked against the value provided to
|
56
|
+
# this Argument.
|
57
|
+
attr_reader :greater_than_validation
|
58
|
+
attr_reader :greater_than_or_equal_to_validation
|
59
|
+
attr_reader :less_than_validation
|
60
|
+
attr_reader :less_than_or_equal_to_validation
|
61
|
+
attr_reader :format_validation
|
62
|
+
attr_reader :equal_to_validation
|
63
|
+
attr_reader :in_validation
|
64
|
+
attr_reader :not_in_validation
|
65
|
+
attr_reader :length_validation
|
66
|
+
|
67
|
+
# Create a new Attribute object.
|
68
|
+
#
|
69
|
+
# `name` must be a symbol.
|
70
|
+
# `required` is a boolean which determines if this Attribute must be provided when
|
71
|
+
# calling its associated DSLMethod.
|
72
|
+
# `type` can be either :integer, :boolean, :float, :string or :symbol
|
73
|
+
# `block` contains the instructions to further configure this Attribute
|
74
|
+
def initialize name, required, type, &block
|
75
|
+
if name.is_a? Symbol
|
76
|
+
@name = name
|
77
|
+
else
|
78
|
+
raise InvalidNameError
|
79
|
+
end
|
80
|
+
|
81
|
+
if type == :integer || type == :boolean || type == :float || type == :string || type == :symbol
|
82
|
+
@type = type
|
83
|
+
else
|
84
|
+
raise InvalidTypeError
|
85
|
+
end
|
86
|
+
|
87
|
+
@required = required ? true : false
|
88
|
+
|
89
|
+
# If a block was provided, then we evaluate it using a seperate
|
90
|
+
# interpreter class. We do this because the interpreter class contains
|
91
|
+
# no other methods or variables, if it was evaluated in the context of
|
92
|
+
# this class then the block would have access to all of the methods defined
|
93
|
+
# in here.
|
94
|
+
if block
|
95
|
+
Interpreter.new(self).instance_eval(&block)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Set the description for this Argument to the provided value.
|
100
|
+
#
|
101
|
+
# `description` must be a string with a length greater than 0.
|
102
|
+
# The `description` can only be set once per Argument
|
103
|
+
def set_description description
|
104
|
+
unless description.is_a?(String) && description.length > 0
|
105
|
+
raise InvalidDescriptionError
|
106
|
+
end
|
107
|
+
|
108
|
+
if has_description?
|
109
|
+
raise DescriptionAlreadyExistsError
|
110
|
+
end
|
111
|
+
|
112
|
+
@description = description
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns `true` if this DSL has a description, else false.
|
116
|
+
def has_description?
|
117
|
+
@description.nil? == false
|
118
|
+
end
|
119
|
+
|
120
|
+
# returns true if this DSLMethod is flagged as required, otherwise returns false.
|
121
|
+
def required?
|
122
|
+
@required == true
|
123
|
+
end
|
124
|
+
|
125
|
+
# returns true if this DSLMethod is flagged as optional, otherwise returns false.
|
126
|
+
def optional?
|
127
|
+
@required == false
|
128
|
+
end
|
129
|
+
|
130
|
+
def validate_greater_than value
|
131
|
+
if @greater_than_validation
|
132
|
+
raise ValidationAlreadyExistsError
|
133
|
+
end
|
134
|
+
|
135
|
+
unless @type == :integer || @type == :float
|
136
|
+
raise ValidationIncompatibleError
|
137
|
+
end
|
138
|
+
|
139
|
+
@greater_than_validation = GreaterThanValidation.new value
|
140
|
+
end
|
141
|
+
|
142
|
+
def validate_greater_than_or_equal_to value
|
143
|
+
if @greater_than_or_equal_to_validation
|
144
|
+
raise ValidationAlreadyExistsError
|
145
|
+
end
|
146
|
+
|
147
|
+
unless value.is_a?(Numeric)
|
148
|
+
raise ValidationInvalidArgumentError
|
149
|
+
end
|
150
|
+
|
151
|
+
unless @type == :integer || @type == :float
|
152
|
+
raise ValidationIncompatibleError
|
153
|
+
end
|
154
|
+
|
155
|
+
@greater_than_or_equal_to_validation = GreaterThanOrEqualToValidation.new value
|
156
|
+
end
|
157
|
+
|
158
|
+
def validate_less_than value
|
159
|
+
if @less_than_validation
|
160
|
+
raise ValidationAlreadyExistsError
|
161
|
+
end
|
162
|
+
|
163
|
+
unless value.is_a?(Numeric)
|
164
|
+
raise ValidationInvalidArgumentError
|
165
|
+
end
|
166
|
+
|
167
|
+
unless @type == :integer || @type == :float
|
168
|
+
raise ValidationIncompatibleError
|
169
|
+
end
|
170
|
+
|
171
|
+
@less_than_validation = LessThanValidation.new value
|
172
|
+
end
|
173
|
+
|
174
|
+
def validate_less_than_or_equal_to value
|
175
|
+
if @less_than_or_equal_to_validation
|
176
|
+
raise ValidationAlreadyExistsError
|
177
|
+
end
|
178
|
+
|
179
|
+
unless value.is_a?(Numeric)
|
180
|
+
raise ValidationInvalidArgumentError
|
181
|
+
end
|
182
|
+
|
183
|
+
unless @type == :integer || @type == :float
|
184
|
+
raise ValidationIncompatibleError
|
185
|
+
end
|
186
|
+
|
187
|
+
@less_than_or_equal_to_validation = LessThanOrEqualToValidation.new value
|
188
|
+
end
|
189
|
+
|
190
|
+
def validate_format regexp
|
191
|
+
if @format_validation
|
192
|
+
raise ValidationAlreadyExistsError
|
193
|
+
end
|
194
|
+
|
195
|
+
unless regexp.is_a? Regexp
|
196
|
+
raise ValidationInvalidArgumentError
|
197
|
+
end
|
198
|
+
|
199
|
+
unless @type == :string || @type == :symbol
|
200
|
+
raise ValidationIncompatibleError
|
201
|
+
end
|
202
|
+
@format_validation = FormatValidation.new regexp
|
203
|
+
end
|
204
|
+
|
205
|
+
def validate_equal_to value
|
206
|
+
if @equal_to_validation
|
207
|
+
raise ValidationAlreadyExistsError
|
208
|
+
end
|
209
|
+
|
210
|
+
unless @type == :integer || @type == :float || @type == :string || @type == :symbol || @type == :boolean
|
211
|
+
raise ValidationIncompatibleError
|
212
|
+
end
|
213
|
+
|
214
|
+
@equal_to_validation = EqualToValidation.new value
|
215
|
+
end
|
216
|
+
|
217
|
+
def validate_in values
|
218
|
+
if @in_validation
|
219
|
+
raise ValidationAlreadyExistsError
|
220
|
+
end
|
221
|
+
|
222
|
+
unless values.is_a? Array
|
223
|
+
raise ValidationInvalidArgumentError
|
224
|
+
end
|
225
|
+
|
226
|
+
unless @type == :integer || @type == :float || @type == :string || @type == :symbol
|
227
|
+
raise ValidationIncompatibleError
|
228
|
+
end
|
229
|
+
|
230
|
+
@in_validation = InValidation.new values
|
231
|
+
end
|
232
|
+
|
233
|
+
def validate_not_in values
|
234
|
+
if @not_in_validation
|
235
|
+
raise ValidationAlreadyExistsError
|
236
|
+
end
|
237
|
+
|
238
|
+
unless values.is_a? Array
|
239
|
+
raise ValidationInvalidArgumentError
|
240
|
+
end
|
241
|
+
|
242
|
+
unless @type == :integer || @type == :float || @type == :string || @type == :symbol
|
243
|
+
raise ValidationIncompatibleError
|
244
|
+
end
|
245
|
+
|
246
|
+
@not_in_validation = NotInValidation.new values
|
247
|
+
end
|
248
|
+
|
249
|
+
def validate_length maximum: nil, minimum: nil, is: nil
|
250
|
+
if @length_validation
|
251
|
+
raise ValidationAlreadyExistsError
|
252
|
+
end
|
253
|
+
|
254
|
+
unless @type == :string || @type == :symbol
|
255
|
+
raise ValidationIncompatibleError
|
256
|
+
end
|
257
|
+
|
258
|
+
@length_validation = LengthValidation.new(maximum: maximum, minimum: minimum, is: is)
|
259
|
+
end
|
260
|
+
|
261
|
+
# returns true if every provided integer validation also returns true
|
262
|
+
def validate_integer! value
|
263
|
+
(greater_than_validation.nil? || greater_than_validation.validate!(value)) &&
|
264
|
+
(greater_than_or_equal_to_validation.nil? || greater_than_or_equal_to_validation.validate!(value)) &&
|
265
|
+
(less_than_validation.nil? || less_than_validation.validate!(value)) &&
|
266
|
+
(less_than_or_equal_to_validation.nil? || less_than_or_equal_to_validation.validate!(value)) &&
|
267
|
+
(format_validation.nil? || format_validation.validate!(value)) &&
|
268
|
+
(equal_to_validation.nil? || equal_to_validation.validate!(value)) &&
|
269
|
+
(in_validation.nil? || in_validation.validate!(value)) &&
|
270
|
+
(not_in_validation.nil? || not_in_validation.validate!(value)) &&
|
271
|
+
(length_validation.nil? || length_validation.validate!(value))
|
272
|
+
end
|
273
|
+
|
274
|
+
# returns true if every provided symbol validation also returns true
|
275
|
+
def validate_symbol! value
|
276
|
+
(format_validation.nil? || format_validation.validate!(value)) &&
|
277
|
+
(equal_to_validation.nil? || equal_to_validation.validate!(value)) &&
|
278
|
+
(in_validation.nil? || in_validation.validate!(value)) &&
|
279
|
+
(not_in_validation.nil? || not_in_validation.validate!(value)) &&
|
280
|
+
(length_validation.nil? || length_validation.validate!(value))
|
281
|
+
end
|
282
|
+
|
283
|
+
# returns true if every provided string validation also returns true
|
284
|
+
def validate_string! value
|
285
|
+
(format_validation.nil? || format_validation.validate!(value)) &&
|
286
|
+
(equal_to_validation.nil? || equal_to_validation.validate!(value)) &&
|
287
|
+
(in_validation.nil? || in_validation.validate!(value)) &&
|
288
|
+
(not_in_validation.nil? || not_in_validation.validate!(value)) &&
|
289
|
+
(length_validation.nil? || length_validation.validate!(value))
|
290
|
+
end
|
291
|
+
|
292
|
+
# returns true if every provided boolean validation also returns true
|
293
|
+
def validate_boolean! value
|
294
|
+
(equal_to_validation.nil? || equal_to_validation.validate!(value))
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class ArgumentDoesNotExistError < StandardError
|
7
|
+
def message
|
8
|
+
"This argument does not exist for this DSLMethod"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ArgumentOrderingError < StandardError
|
13
|
+
def message
|
14
|
+
"Required arguments can not be added after optional ones"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ArgumentAlreadyExistsError < StandardError
|
19
|
+
def message
|
20
|
+
"An argument with this name already exists for this DSL method"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class RequestedOptionalArgumentIsRequiredError < StandardError
|
25
|
+
def message
|
26
|
+
"A specific argument which was expected to be optional was requested, but the argument found was flagged as required"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class RequestedRequiredArgumentIsOptionalError < StandardError
|
31
|
+
def message
|
32
|
+
"A specific argument which was expected to be required was requested, but the argument found was flagged as optional"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@arguments = {}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns an array of all this DSLMethods Argument objects.
|
41
|
+
def arguments
|
42
|
+
@arguments.values
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns an array of only the optional Argument objects on this DSLMethod.
|
46
|
+
def optional_arguments
|
47
|
+
arguments.filter(&:optional?)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns an array of only the required Argument objects on this DSLMethod.
|
51
|
+
def required_arguments
|
52
|
+
arguments.filter(&:required?)
|
53
|
+
end
|
54
|
+
|
55
|
+
# returns a specific Argument by it's name, if the Argument does not
|
56
|
+
# exist, then an error is raised
|
57
|
+
def argument name
|
58
|
+
if has_argument? name
|
59
|
+
@arguments[name]
|
60
|
+
else
|
61
|
+
raise ArgumentDoesNotExistError
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# returns a specific optional Argument by it's name, if the Argument does not
|
66
|
+
# exist, or if it is required, then an error is raised
|
67
|
+
def optional_argument name
|
68
|
+
arg = argument name
|
69
|
+
if arg.optional?
|
70
|
+
@arguments[name]
|
71
|
+
else
|
72
|
+
raise RequestedOptionalArgumentIsRequiredError
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# returns a specific required Argument by it's name, if the Argument does not
|
77
|
+
# exist, or if it is optional, then an error is raised
|
78
|
+
def required_argument name
|
79
|
+
arg = argument name
|
80
|
+
if arg.required?
|
81
|
+
@arguments[name]
|
82
|
+
else
|
83
|
+
raise RequestedRequiredArgumentIsOptionalError
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns `true` if an Argument with the provided name exists in this
|
88
|
+
# DSLMethod, otherwise it returns `false`.
|
89
|
+
def has_argument? name
|
90
|
+
@arguments.key? name
|
91
|
+
end
|
92
|
+
|
93
|
+
# Takes a method name, unique flag, required flag, and a block and creates
|
94
|
+
# a new Argument object.
|
95
|
+
#
|
96
|
+
# Argument `name` must be unique within the DSLMethod.
|
97
|
+
# `required` must be a boolean, and determines if this argument will be required
|
98
|
+
# or optional on the method which is exposed in our DSL.
|
99
|
+
def add_argument name, required, type, &block
|
100
|
+
if @arguments.key? name
|
101
|
+
raise ArgumentAlreadyExistsError
|
102
|
+
end
|
103
|
+
|
104
|
+
# required arguments may not come after optional ones
|
105
|
+
if required && optional_arguments.any?
|
106
|
+
raise ArgumentOrderingError
|
107
|
+
end
|
108
|
+
|
109
|
+
@arguments[name] = Argument.new(name, required, type, &block)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class DSLMethod
|
6
|
+
# This class is reponsible for parsing and executing method definitions
|
7
|
+
# within our internal DSL. These method definitions determine what methods
|
8
|
+
# will be available within our new dynamic DSL.
|
9
|
+
#
|
10
|
+
# This class is instantaited by the DSLCompose::DSL::DSLMethod class and the method definition
|
11
|
+
# part of our internal DSL is evaluated by passing a block to `instance_eval` on this class.
|
12
|
+
#
|
13
|
+
# An example of our internal DSL which includes a complex method definition:
|
14
|
+
# define_dsl :my_dsl do
|
15
|
+
# add_method :my_method, required: true do
|
16
|
+
# description "Description of my method"
|
17
|
+
# optional :my_optional_argument, :string do
|
18
|
+
# # ...
|
19
|
+
# end
|
20
|
+
# optional :my_optional_arg, String
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
class Interpreter
|
24
|
+
def initialize dsl_method
|
25
|
+
@dsl_method = dsl_method
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# sets the description of the DSLMethod
|
31
|
+
def description description
|
32
|
+
@dsl_method.set_description description
|
33
|
+
end
|
34
|
+
|
35
|
+
# adds a new optional argument to the DSLMethod
|
36
|
+
#
|
37
|
+
# name must be a symbol
|
38
|
+
# `type` can be either :integer, :boolean, :float, :string or :symbol
|
39
|
+
# `block` contains the argument definition and will be evaluated seperately
|
40
|
+
# by the Argument::Interpreter
|
41
|
+
def optional name, type, &block
|
42
|
+
@dsl_method.arguments.add_argument name, false, type, &block
|
43
|
+
end
|
44
|
+
|
45
|
+
# adds a new required argument to the DSLMethod
|
46
|
+
#
|
47
|
+
# name must be a symbol
|
48
|
+
# `type` can be either :integer, :boolean, :float, :string or :symbol
|
49
|
+
# `block` contains the argument definition and will be evaluated seperately
|
50
|
+
# by the Argument::Interpreter
|
51
|
+
def requires name, type, &block
|
52
|
+
@dsl_method.arguments.add_argument name, true, type, &block
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|