dsl_compose 1.2.0 → 1.4.0

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
  SHA256:
3
- metadata.gz: 2cb2c822a8b9538706989731334fe26334b83e65a59d2e9ecb124f90683273ed
4
- data.tar.gz: e82f983c0bb311bf57458546e8539842f6ba722252f64d200b39467b0045994d
3
+ metadata.gz: c1a173b5c152d3e0e4ac3867b9f55989593a82f724ad27c26aa0445500c81295
4
+ data.tar.gz: 391d451dcef58cf46915b0b54249b527097210d916aa041e1d49de4c576845d8
5
5
  SHA512:
6
- metadata.gz: fe00a6f40481346f1eea34ed6f864dd70661d7bfb70753bd2142d793f3c5bf93f2999521cbcb19ddf3082bf11bac8613f2424fa5f4de2edf3345c13d12984ad6
7
- data.tar.gz: ad22470dd58fc30f6c5e2918afd60e3c6e22fea32dbee021fbb93aeabaa21a58de61e78c92d90d1399c9142e8d836375722efe21e5094df7135ba0bfefd12584
6
+ metadata.gz: 9d049bc5ed8c830468376cefcb198fc2671c7eff26b9a0a3fff33377d0ac2c27c03f2b2c2fa1527ef648a847667d5fe58b814c355f058e5cb3bceb80439e0ac7
7
+ data.tar.gz: 7af648a16098f0ce9b6a0c20936b0b87195cf0e2c8e7869769b5ff293d059b6ca39a0da30b15fb1605d558faeaf5965e616c3cb253bc34daec6e683879ee4da9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.4.0](https://github.com/craigulliott/dsl_compose/compare/v1.3.0...v1.4.0) (2023-06-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * added a Parser class which can be used to react to any DSLs which have been defined and used ([8d2f16b](https://github.com/craigulliott/dsl_compose/commit/8d2f16b67ae98486a47e6e8d6d6af81be508cb06))
9
+
10
+ ## [1.3.0](https://github.com/craigulliott/dsl_compose/compare/v1.2.0...v1.3.0) (2023-06-22)
11
+
12
+
13
+ ### Features
14
+
15
+ * adding an executions_by_class method to make processing the configuration more convenient ([#8](https://github.com/craigulliott/dsl_compose/issues/8)) ([313507c](https://github.com/craigulliott/dsl_compose/commit/313507ca572f59c03162a91d58e62500a9464f25))
16
+ * fixing release please job ([#10](https://github.com/craigulliott/dsl_compose/issues/10)) ([880fa5b](https://github.com/craigulliott/dsl_compose/commit/880fa5b2aceed67aa9ff1e7cf53629af23e31b10))
17
+
3
18
  ## [1.2.0](https://github.com/craigulliott/dsl_compose/compare/v1.1.0...v1.2.0) (2023-06-22)
4
19
 
5
20
 
data/README.md CHANGED
@@ -13,7 +13,7 @@ Ruby gem to add dynamic DSLs to classes
13
13
  * Takes special care not to pollute the namespace of classes where it is used
14
14
  * Use of your declared DSLs is validated at run time
15
15
  * Automatically generate documentation and instructions for your DSLs
16
- * Complete test covereage
16
+ * Complete test coverage
17
17
  * Very lightweight and no external dependencies
18
18
 
19
19
  ## Installation
@@ -28,7 +28,7 @@ If bundler is not being used to manage dependencies, install the gem by executin
28
28
 
29
29
  ## Usage
30
30
 
31
- DSLs are added to classes by including the DSLCompose module, and then calling the add_dsl singleton method within the class or a child class.
31
+ DSLs are added to classes by including the DSLCompose::Composer module, and then calling the define_dsl singleton method within the class or a child class.
32
32
 
33
33
  ### Defining your DSL
34
34
 
@@ -48,6 +48,18 @@ class Foo
48
48
  You can use **Markdown** in this description.
49
49
  DESCRIPTION
50
50
 
51
+ # You can add required or optional arguments to the initial method which is used
52
+ # to enter your dynamic DSL (for optional arguments, use `optional` instead of
53
+ # `required`).
54
+ #
55
+ # Arguments are validated, and their expected type must be defined. Supported
56
+ # argument types are :integer, :boolean, :float, :string or :symbol
57
+ requires :first_dsl_argument, :symbol do
58
+ # You should provide descriptions for your arguments. These descriptions will
59
+ # be used when generating your documentation. This description supports markdown
60
+ description "A description of the first argument for this method"
61
+ end
62
+
51
63
  # Define a method which will be available within your DSL. These
52
64
  # methods will be exposed inside your DSL and can be called multiple times.
53
65
  add_method :an_optional_method do
@@ -83,7 +95,7 @@ class Foo
83
95
  #
84
96
  # Arguments are validated, and their expected type must be defined. Supported
85
97
  # argument types are :integer, :boolean, :float, :string or :symbol
86
- requires :my_first_argument, :symbol do
98
+ requires :first_method_argument, :string do
87
99
  # You should provide descriptions for your arguments. These descriptions will
88
100
  # be used when generating your documentation. This description supports markdown
89
101
  description "A description of the first argument for this method"
@@ -92,7 +104,7 @@ class Foo
92
104
  # You can also add optional arguments to your DSL methods. All optional
93
105
  # arguments must be added after required ones. An error will be raised if
94
106
  # you define a required argument after an optional one.
95
- optional :an_optional_argument, :integer do
107
+ optional :optional_argument, :integer do
96
108
  description "A description of an optional argument"
97
109
 
98
110
  # You can add validation to your arguments. A full list is provided later in this document
@@ -112,8 +124,8 @@ Child classes can then use your new DSL
112
124
  ```ruby
113
125
  class Bar << Foo
114
126
 
115
- my_dsl do
116
- my_method my_first_argument, my_second_argument, optional_arg: optional_arg_value
127
+ my_dsl :first_dsl_argument, do
128
+ my_method "first_method_argument", optional_argument: 123
117
129
  end
118
130
 
119
131
  end
@@ -175,6 +187,48 @@ MyClientLibrary.configure do
175
187
  end
176
188
  ```
177
189
 
190
+ ## Parsing complicated DSLs
191
+
192
+ A parser class can be used to process complicated DSLs. In the example below, a base class named SomeBaseClass has DSLs named :dsl1, and :dsl2.
193
+
194
+ ```ruby
195
+ # create your own parser by creating a new class which extends DSLCompose::Parser
196
+ MyParser < DSLCompose::Parser
197
+ # `for_children_of` will process SomeBaseClass and yield the provided
198
+ # block once for every class which extends SomeBaseClass and uses at
199
+ # least one of the DSLs that have been defined on it.
200
+ for_children_of SomeBaseClass do |child_class:|
201
+ # `for_dsl` accepts a DSL name or an array of DSL names and will yield
202
+ # it's provided block once for each time a DSL of that name has been
203
+ # used on the child_class.
204
+ #
205
+ # An error will be raised if any of the provided DSL names does not exist
206
+ #
207
+ # You can optionally provide keyword arguments which correspond to any
208
+ # arguments that were defined for the DSL, if multiple dsl names are provided
209
+ # then the requested dsl argument must be present on all DSLs otherwise an
210
+ # error will be raised.
211
+ for_dsl [:dsl1, :dsl2] do |dsl_name:, a_dsl_argument:|
212
+ # `for_method` accepts a method name or an array of method names and will
213
+ # yield it's provided block once for each time a method with this name is
214
+ # executed within the DSL.
215
+ #
216
+ # An error will be raised if any of the provided method names does not exist
217
+ #
218
+ # You can optionally provide keyword arguments which correspond to any
219
+ # arguments that were defined for the DSL method, if multiple method names
220
+ # are provided then the requested dsl argument must be present on all DSLs
221
+ # otherwise an error will be raised.
222
+ for_method :some_method_name do |method_name:, a_method_argument:|
223
+ # your business logic goes here
224
+ ...
225
+ end
226
+ end
227
+ end
228
+ end
229
+ ```
230
+
231
+
178
232
  ## Argument validations
179
233
 
180
234
  The following validations can be added to the arguments of your DSL methods. Validations can be added to both required and optional arguments, and you can add multiple validations to each argument.
@@ -10,13 +10,13 @@ module DSLCompose
10
10
 
11
11
  class MethodAlreadyExistsWithThisDSLNameError < StandardError
12
12
  def message
13
- "The define_dsl singleton method already exists for this class."
13
+ "The `define_dsl` singleton method already exists for this class."
14
14
  end
15
15
  end
16
16
 
17
17
  class GetDSLExecutionResultsMethodAlreadyExistsError < StandardError
18
18
  def message
19
- "The dsl_interpreter singleton method already exists for this class."
19
+ "The `dsls` singleton method already exists for this class."
20
20
  end
21
21
  end
22
22
 
@@ -30,11 +30,11 @@ module DSLCompose
30
30
  interpreter = DSLCompose::Interpreter.new
31
31
 
32
32
  # return a specific DSL which is defined for this class
33
- if klass.respond_to? :dsl_interpreter
33
+ if klass.respond_to? :dsls
34
34
  raise GetDSLExecutionResultsMethodAlreadyExistsError
35
35
  end
36
36
 
37
- klass.define_singleton_method :dsl_interpreter do
37
+ klass.define_singleton_method :dsls do
38
38
  interpreter
39
39
  end
40
40
 
@@ -40,6 +40,18 @@ module DSLCompose
40
40
  end
41
41
  end
42
42
 
43
+ class ArgumentNameReservedError < StandardError
44
+ def message
45
+ "This argument name is a reserved word. The names #{RESERVED_ARGUMENT_NAMES.join ", "} can not be used here because the Parser uses it to express a structural part of the DSL"
46
+ end
47
+ end
48
+
49
+ RESERVED_ARGUMENT_NAMES = [
50
+ :child_class,
51
+ :dsl_name,
52
+ :method_name
53
+ ].freeze
54
+
43
55
  # The name of this Argument.
44
56
  attr_reader :name
45
57
  # An arguments type. This determines what kind of value can be passed when calling the
@@ -73,6 +85,11 @@ module DSLCompose
73
85
  # `block` contains the instructions to further configure this Attribute
74
86
  def initialize name, required, type, &block
75
87
  if name.is_a? Symbol
88
+
89
+ if RESERVED_ARGUMENT_NAMES.include? name
90
+ raise ArgumentNameReservedError
91
+ end
92
+
76
93
  @name = name
77
94
  else
78
95
  raise InvalidNameError
@@ -6,13 +6,13 @@ module DSLCompose
6
6
  class Arguments
7
7
  class MissingRequiredArgumentsError < StandardError
8
8
  def initialize required_count, provided_count
9
- super "This method requires #{required_count} arguments, but only #{required_count} were provided"
9
+ super "This requires #{required_count} arguments, but only #{provided_count} were provided"
10
10
  end
11
11
  end
12
12
 
13
13
  class TooManyArgumentsError < StandardError
14
14
  def message
15
- "Too many arguments provided to this method"
15
+ "Too many arguments provided"
16
16
  end
17
17
  end
18
18
 
@@ -19,6 +19,10 @@ module DSLCompose
19
19
  @method_calls << method_call
20
20
  method_call
21
21
  end
22
+
23
+ def method_calls_by_name method_name
24
+ @method_calls.filter { |mc| mc.method_name == method_name }
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -27,11 +27,16 @@ module DSLCompose
27
27
  @executions.filter { |e| e.klass == klass }
28
28
  end
29
29
 
30
- # Returns an array of all executions for a given class.
30
+ # Returns an array of all executions for a given name.
31
31
  def dsl_executions dsl_name
32
32
  @executions.filter { |e| e.dsl.name == dsl_name }
33
33
  end
34
34
 
35
+ # Returns an array of all executions for a given name and class.
36
+ def class_dsl_executions klass, dsl_name
37
+ @executions.filter { |e| e.klass == klass && e.dsl.name == dsl_name }
38
+ end
39
+
35
40
  def to_h dsl_name
36
41
  h = {}
37
42
  dsl_executions(dsl_name).each do |execution|
@@ -46,5 +51,23 @@ module DSLCompose
46
51
  end
47
52
  h
48
53
  end
54
+
55
+ def executions_by_class
56
+ h = {}
57
+ executions.each do |execution|
58
+ h[execution.klass] ||= {}
59
+ h[execution.klass][execution.dsl.name] ||= []
60
+ execution_h = {
61
+ arguments: execution.arguments.to_h,
62
+ method_calls: {}
63
+ }
64
+ execution.method_calls.method_calls.each do |method_call|
65
+ execution_h[:method_calls][method_call.method_name] ||= []
66
+ execution_h[:method_calls][method_call.method_name] << method_call.to_h
67
+ end
68
+ h[execution.klass][execution.dsl.name] << execution_h
69
+ end
70
+ h
71
+ end
49
72
  end
50
73
  end
@@ -0,0 +1,9 @@
1
+ module DSLCompose
2
+ class Parser
3
+ class BlockArguments
4
+ def self.accepts_argument? arg_name, &block
5
+ block.parameters.any? { |type, name| name == arg_name }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DSLCompose
4
+ class Parser
5
+ class ForChildrenOfParser
6
+ class ForDSLParser
7
+ class ForMethodParser
8
+ class AllBlockParametersMustBeKeywordParametersError < StandardError
9
+ def message
10
+ "All block parameters must be keyword parameters, i.e. `for_children_of FooClass do |base_class:|`"
11
+ end
12
+ end
13
+
14
+ class NoBlockProvided < StandardError
15
+ end
16
+
17
+ class MethodDoesNotExistError < StandardError
18
+ end
19
+
20
+ class MethodNamesShouldBeSymbolsError < StandardError
21
+ def message
22
+ "Method names must be provided with a symbol or array of symbols"
23
+ end
24
+ end
25
+
26
+ # This class will yield to the provided block once for each time a method
27
+ # with the provided name is called within a DSL called on the child class.
28
+ #
29
+ # base_class and child_class are set from the ForChildrenOfParser
30
+ # dsl_execution is set from the ForDSLParser
31
+ def initialize base_class, child_class, dsl_execution, method_names, &block
32
+ @base_class = base_class
33
+ @child_class = child_class
34
+ @dsl_execution = dsl_execution
35
+ @method_names = method_names
36
+
37
+ # assert that a block was provided
38
+ unless block
39
+ raise NoBlockProvided
40
+ end
41
+
42
+ # if any arguments were provided, then assert that they are valid
43
+ if block.parameters.any?
44
+ # all parameters must be keyword arguments
45
+ if block.parameters.filter { |p| p.first != :keyreq }.any?
46
+ raise AllBlockParametersMustBeKeywordParametersError
47
+ end
48
+ end
49
+
50
+ # if the provided dsl name is a symbol, then convert it to an array
51
+ if method_names.is_a? Symbol
52
+ method_names = [method_names]
53
+ end
54
+
55
+ # assert that the provided dsl name is an array
56
+ unless method_names.is_a? Array
57
+ raise MethodNamesShouldBeSymbolsError
58
+ end
59
+
60
+ # assert that the provided dsl name is an array of symbols
61
+ unless method_names.all? { |method_name| method_name.is_a? Symbol }
62
+ raise MethodNamesShouldBeSymbolsError
63
+ end
64
+
65
+ # assert that the provided method names all exist for the scoped DSL
66
+ unless method_names.all? { |method_name| dsl_execution.dsl.has_dsl_method?(method_name) }
67
+ raise MethodDoesNotExistError
68
+ end
69
+
70
+ # for each provided dsl name, yield to the provided block
71
+ method_names.each do |method_name|
72
+ # we only provide the requested arguments to the block, this allows
73
+ # us to use keyword arguments to force a naming convention on these arguments
74
+ # and to validate their use
75
+ args = {}
76
+ if BlockArguments.accepts_argument?(:method_name, &block)
77
+ args[:method_name] = method_name
78
+ end
79
+
80
+ # methods can be executed multiple times, so yield once for each method call
81
+ # add any arguments that were provided to the DSL method
82
+ dsl_execution.method_calls.method_calls_by_name(method_name).each do |method_call|
83
+ # add any arguments that were provided to the method call
84
+ method_call.arguments.arguments.each do |name, value|
85
+ if BlockArguments.accepts_argument?(name, &block)
86
+ args[name] = value
87
+ end
88
+ end
89
+
90
+ # yeild the block in the context of this class
91
+ instance_exec(**args, &block)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DSLCompose
4
+ class Parser
5
+ class ForChildrenOfParser
6
+ class ForDSLParser
7
+ class AllBlockParametersMustBeKeywordParametersError < StandardError
8
+ def message
9
+ "All block parameters must be keyword parameters, i.e. `for_dsl :dsl_name do |dsl_name:|`"
10
+ end
11
+ end
12
+
13
+ class NoBlockProvided < StandardError
14
+ end
15
+
16
+ class DSLDoesNotExistError < StandardError
17
+ end
18
+
19
+ class DSLNamesShouldBeSymbolsError < StandardError
20
+ def message
21
+ "DSL names must be provided with a symbol or array of symbols"
22
+ end
23
+ end
24
+
25
+ # This class will yield to the provided block once for each time a DSL
26
+ # of the provided name is used by the child class.
27
+ #
28
+ # base_class and child_class are set from the ForChildrenOfParser
29
+ def initialize base_class, child_class, dsl_names, &block
30
+ @base_class = base_class
31
+ @child_class = child_class
32
+ @dsl_names = dsl_names
33
+
34
+ # assert that a block was provided
35
+ unless block
36
+ raise NoBlockProvided
37
+ end
38
+
39
+ # if any arguments were provided, then assert that they are valid
40
+ if block.parameters.any?
41
+ # all parameters must be keyword arguments
42
+ if block.parameters.filter { |p| p.first != :keyreq }.any?
43
+ raise AllBlockParametersMustBeKeywordParametersError
44
+ end
45
+ end
46
+
47
+ # if the provided dsl name is a symbol, then convert it to an array
48
+ if dsl_names.is_a? Symbol
49
+ dsl_names = [dsl_names]
50
+ end
51
+
52
+ # assert that the provided dsl name is an array
53
+ unless dsl_names.is_a? Array
54
+ raise DSLNamesShouldBeSymbolsError
55
+ end
56
+
57
+ # assert that the provided dsl name is an array of symbols
58
+ unless dsl_names.all? { |dsl_name| dsl_name.is_a? Symbol }
59
+ raise DSLNamesShouldBeSymbolsError
60
+ end
61
+
62
+ # assert that the provided dsl names all exist
63
+ unless dsl_names.all? { |dsl_name| DSLs.class_dsl_exists?(base_class, dsl_name) }
64
+ raise DSLDoesNotExistError
65
+ end
66
+
67
+ # for each provided dsl name, yield to the provided block
68
+ dsl_names.each do |dsl_name|
69
+ # a dsl can be execued multiple times on a class, so we find all of the executions
70
+ # here and then yield the block once for each execution
71
+ base_class.dsls.class_dsl_executions(child_class, dsl_name).each do |dsl_execution|
72
+ # we only provide the requested arguments to the block, this allows
73
+ # us to use keyword arguments to force a naming convention on these arguments
74
+ # and to validate their use
75
+ args = {}
76
+ if BlockArguments.accepts_argument?(:dsl_name, &block)
77
+ args[:dsl_name] = dsl_execution.dsl.name
78
+ end
79
+ # add any arguments that were provided to the DSL
80
+ dsl_execution.arguments.arguments.each do |name, value|
81
+ if BlockArguments.accepts_argument?(name, &block)
82
+ args[name] = value
83
+ end
84
+ end
85
+ # set the dsl_execution in an instance variable so that method calls to `for_method`
86
+ # from within the block will have access to it
87
+ @dsl_execution = dsl_execution
88
+ # yield the block in the context of this class
89
+ instance_exec(**args, &block)
90
+ end
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ # Given a method name, or array of method names, this method will yield to the
97
+ # provided block once for each time a dsl method with one of the provided names
98
+ # was used within one of the correspondng dsls, on each child_class
99
+ #
100
+ # The values of base_class and child_class are set from the yield of the parent
101
+ # class (ForChildrenOfParser) initializer, the value of dsl_execution is set from
102
+ # this classes initializer, meaning that the use of this method should look
103
+ # something like this:
104
+ #
105
+ # for_children_of PlatformRecord do |base_class:|
106
+ # for_dsl [:number_field, :float_field] do |name:|
107
+ # for_method :some_method_name do |method_name:, a_method_argument:|
108
+ # ...
109
+ # end
110
+ # end
111
+ # end
112
+ def for_method method_names, &block
113
+ ForMethodParser.new(@base_class, @child_class, @dsl_execution, method_names, &block)
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DSLCompose
4
+ class Parser
5
+ class ForChildrenOfParser
6
+ class AllBlockParametersMustBeKeywordParametersError < StandardError
7
+ def message
8
+ "All block parameters must be keyword parameters, i.e. `for_children_of FooClass do |base_class:|`"
9
+ end
10
+ end
11
+
12
+ class ClassDoesNotUseDSLComposeError < StandardError
13
+ end
14
+
15
+ class NoBlockProvided < StandardError
16
+ end
17
+
18
+ class NoChildClassError < StandardError
19
+ def message
20
+ "No child_class was found, please call this method from within a `for_children_of` block"
21
+ end
22
+ end
23
+
24
+ # This class will yield to the provided block for each class which extends the base_class, provided
25
+ # that the child also uses at least one of the DSLs which have been defined on the base_class
26
+ def initialize base_class, &block
27
+ # assert the provided class has the DSLCompose::Composer module installed
28
+ unless base_class.respond_to? :dsls
29
+ raise ClassDoesNotUseDSLComposeError
30
+ end
31
+
32
+ @base_class = base_class
33
+
34
+ # assert that a block was provided
35
+ unless block
36
+ raise NoBlockProvided
37
+ end
38
+
39
+ # if any arguments were provided, then assert that they are valid
40
+ if block.parameters.any?
41
+ # all parameters must be keyword arguments
42
+ if block.parameters.filter { |p| p.first != :keyreq }.any?
43
+ raise AllBlockParametersMustBeKeywordParametersError
44
+ end
45
+ end
46
+
47
+ # yield the provided block for each child class of the provided base_class
48
+ # which uses a defined DSL
49
+ base_class.dsls.executions_by_class.each do |child_class, dsl|
50
+ args = {}
51
+ if BlockArguments.accepts_argument?(:child_class, &block)
52
+ args[:child_class] = child_class
53
+ end
54
+ # set the child_class in an instance variable so that method calls to
55
+ # `for_dsl` from within the block will have access to it
56
+ @child_class = child_class
57
+ # yield the block in the context of this class
58
+ instance_exec(**args, &block)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ # Given a dsl name, or array of dsl names, this method will yield to the
65
+ # provided block once for each time a dsl with one of the provided names
66
+ # was used on the correspondng child_class
67
+ #
68
+ # The value of child_class and base_class are set from the yield of this
69
+ # classes initializer, meaning that the use of this method should look
70
+ # something like this:
71
+ #
72
+ # for_children_of PlatformRecord do |base_class:|
73
+ # for_dsl [:number_field, :float_field] do |name:|
74
+ # ...
75
+ # end
76
+ # end
77
+ def for_dsl dsl_names, &block
78
+ child_class = @child_class
79
+
80
+ unless child_class
81
+ raise NoChildClassError
82
+ end
83
+
84
+ ForDSLParser.new(@base_class, child_class, dsl_names, &block)
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DSLCompose
4
+ # A base class for building parsers which can be used to act upon
5
+ # our dynamically defined DSLs
6
+ #
7
+ # Example syntax...
8
+ #
9
+ # for_children_of SomeBaseClass do |child_class:|
10
+ # for_dsl [:dsl_name1, :dsl_name2] do |dsl_name:, a_dsl_argument:|
11
+ # for_method :some_method_name do |method_name:, a_method_argument:|
12
+ # ...
13
+ # end
14
+ # end
15
+ # end
16
+ class Parser
17
+ class NotInitializable < StandardError
18
+ end
19
+
20
+ # this class is not designed to be initialized, the parser is made up of
21
+ # singlerton methods and is designed to be executed as soon as it is required
22
+ # into an application
23
+ def initialize
24
+ raise NotInitializable
25
+ end
26
+
27
+ # the first step in defining a parser is to set the base_class, this method
28
+ # will yield to the provided block for each child class of the provided base_class
29
+ # provided that the child_class uses at least one of the base_classes defined DSLs
30
+ def self.for_children_of base_class, &block
31
+ # we parse the provided block in the context of the ForChildrenOfParser class
32
+ # to help make this code more readable, and to limit polluting the current namespace
33
+ ForChildrenOfParser.new(base_class, &block)
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DSLCompose
4
- VERSION = "1.2.0"
4
+ VERSION = "1.4.0"
5
5
  end
data/lib/dsl_compose.rb CHANGED
@@ -29,6 +29,12 @@ require "dsl_compose/interpreter/execution/arguments"
29
29
  require "dsl_compose/interpreter/execution"
30
30
  require "dsl_compose/interpreter"
31
31
 
32
+ require "dsl_compose/parser/for_children_of_parser/for_dsl_parser/for_method_parser"
33
+ require "dsl_compose/parser/for_children_of_parser/for_dsl_parser"
34
+ require "dsl_compose/parser/for_children_of_parser"
35
+ require "dsl_compose/parser/block_arguments"
36
+ require "dsl_compose/parser"
37
+
32
38
  require "dsl_compose/composer"
33
39
 
34
40
  require "dsl_compose/dsls"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dsl_compose
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Ulliott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-22 00:00:00.000000000 Z
11
+ date: 2023-06-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby gem to add dynamic DSLs to classes. DSLs are added to classes by
14
14
  including the DSLCompose module, and then calling the add_dsl singleton method within
@@ -47,6 +47,11 @@ files:
47
47
  - lib/dsl_compose/interpreter/execution/arguments.rb
48
48
  - lib/dsl_compose/interpreter/execution/method_calls.rb
49
49
  - lib/dsl_compose/interpreter/execution/method_calls/method_call.rb
50
+ - lib/dsl_compose/parser.rb
51
+ - lib/dsl_compose/parser/block_arguments.rb
52
+ - lib/dsl_compose/parser/for_children_of_parser.rb
53
+ - lib/dsl_compose/parser/for_children_of_parser/for_dsl_parser.rb
54
+ - lib/dsl_compose/parser/for_children_of_parser/for_dsl_parser/for_method_parser.rb
50
55
  - lib/dsl_compose/version.rb
51
56
  homepage:
52
57
  licenses: