dsl_compose 2.15.1 → 2.15.4

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: ae01b58f13f59318a89b06b444bd0dc0a17487e66d03a7701cb605673774f75a
4
- data.tar.gz: 2feeab8f8494a6dea3ee59c52903a21c84cde2da623f406aea9530581146d124
3
+ metadata.gz: 0c630022da7a35c7bb15fcb5847b3036dc21e45b0afd950edb4fa6bb205147f4
4
+ data.tar.gz: ed8a49a2b1ec77a4a741a1eeaddd4fb52019ad307cf96c2d8f531f1df4d24a7f
5
5
  SHA512:
6
- metadata.gz: 6d1b476aef66fcaf034b3e7775a91233b69f30dc46c1dfc6d2891596ed859d0a9219e69c7bfec5ede49179d56a0fa2e59f31398b5b95504eb8ebd72c6f9a4d01
7
- data.tar.gz: 565b63fb9b5e24f6d778e74f477b7aea4cd6619bfb39aa5ae62a9651daffd5b54e06ceaa8cef3378c111b508babe89d55d02af768c0692f24e4be9c68ad23845
6
+ metadata.gz: 96aa671032ce71ce1d7639ab8fbf25d7e3f17d58f3b822a1601b6af99808502083d284b4f6cbea7541dc271a8d1dcf0e005f98d066852d86a9b88d3e194125cb
7
+ data.tar.gz: 5d17dfa43b30dae88aebdff5bc192d083fa3cf668e896a9fb71c314304b9b8320a4dfb6444b1055b8fde0d0da45d0285d38982ae7cbcf006d93f1c634d86ca38
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.15.4](https://github.com/craigulliott/dsl_compose/compare/v2.15.3...v2.15.4) (2023-10-04)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * passing context along with where DSL's were defined, and then including this context in error messages ([5238a3d](https://github.com/craigulliott/dsl_compose/commit/5238a3daa8c1a32e77783d56c7c429b6335995bd))
9
+
10
+ ## [2.15.3](https://github.com/craigulliott/dsl_compose/compare/v2.15.2...v2.15.3) (2023-10-03)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * updating class sorting method so that it is stable (we were getting different results on ubuntu/the CI server) ([70139a1](https://github.com/craigulliott/dsl_compose/commit/70139a11fa5190c3019e95199656385676a10177))
16
+
17
+ ## [2.15.2](https://github.com/craigulliott/dsl_compose/compare/v2.15.1...v2.15.2) (2023-10-03)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * fix: sorting classes by ancestry chain (i.e. ancestors before descendants) in the parser ([c301c4b](https://github.com/craigulliott/dsl_compose/commit/c301c4b9e1393c996d5b29dd7a6fd0e2758ae109))
23
+
3
24
  ## [2.15.1](https://github.com/craigulliott/dsl_compose/compare/v2.15.0...v2.15.1) (2023-10-03)
4
25
 
5
26
 
@@ -48,9 +48,11 @@ module DSLCompose
48
48
 
49
49
  # add a singleton method with the name of this new DSL onto our class, this is how our new DSL will be accessed
50
50
  define_singleton_method name do |*args, &block|
51
+ called_from = caller(1..1).first
52
+
51
53
  # when it is called, we process this new dynamic DSL with the interpreter
52
54
  # `self` here is the class in which the dsl is being used, not the class in which the DSL was defined
53
- interpreter.execute_dsl self, dsl, *args, &block
55
+ interpreter.execute_dsl self, dsl, called_from, *args, &block
54
56
  end
55
57
 
56
58
  end
@@ -127,7 +127,7 @@ module DSLCompose
127
127
  Interpreter.new(self).instance_eval(&block)
128
128
  end
129
129
  rescue => e
130
- raise e, "Error defining argument #{name}: #{e.message}", e.backtrace
130
+ raise e, "Error while defining argument #{name}\n#{e.message}", e.backtrace
131
131
  end
132
132
 
133
133
  # Set the description for this Argument to the provided value.
@@ -60,7 +60,7 @@ module DSLCompose
60
60
  Interpreter.new(self).instance_eval(&block)
61
61
  end
62
62
  rescue => e
63
- raise e, "Error defining method #{name}: #{e.message}", e.backtrace
63
+ raise e, "Error while defining method #{name}\n#{e.message}", e.backtrace
64
64
  end
65
65
 
66
66
  # Set the description for this DSLMethod to the provided value.
@@ -83,8 +83,6 @@ module DSLCompose
83
83
  else
84
84
  raise NoBlockProvidedError, "No block was provided for this DSL"
85
85
  end
86
- rescue => e
87
- raise e, "Error defining DSL #{@name} on #{@klass}: #{e.message}", e.backtrace
88
86
  end
89
87
 
90
88
  # Set the description for this DSL to the provided value.
@@ -4,25 +4,27 @@ module DSLCompose
4
4
  class Interpreter
5
5
  class Execution
6
6
  class Arguments
7
- class MissingRequiredArgumentsError < StandardError
7
+ class MissingRequiredArgumentsError < InterpreterError
8
8
  end
9
9
 
10
- class TooManyArgumentsError < StandardError
10
+ class TooManyArgumentsError < InterpreterError
11
11
  end
12
12
 
13
- class OptionalArgumentsShouldBeHashError < StandardError
13
+ class OptionalArgumentsShouldBeHashError < InterpreterError
14
14
  end
15
15
 
16
- class InvalidArgumentTypeError < StandardError
16
+ class InvalidArgumentTypeError < InterpreterError
17
17
  end
18
18
 
19
- class ArrayNotValidError < StandardError
19
+ class ArrayNotValidError < InterpreterError
20
20
  end
21
21
 
22
22
  attr_reader :arguments
23
+ attr_reader :called_from
23
24
 
24
- def initialize arguments, *args
25
+ def initialize arguments, called_from, *args
25
26
  @arguments = {}
27
+ @called_from = called_from
26
28
 
27
29
  required_argument_count = arguments.required_arguments.count
28
30
  required_non_kwarg_argument_count = arguments.required_arguments.count { |a| !a.kwarg }
@@ -40,7 +42,7 @@ module DSLCompose
40
42
  required_kwargs = arguments.required_arguments.filter { |a| a.kwarg }
41
43
 
42
44
  if required_kwargs.any? && !all_kwargs.is_a?(Hash)
43
- raise MissingRequiredArgumentsError, "This has required keyword arguments, but no keyword arguments were provided"
45
+ raise MissingRequiredArgumentsError.new("This has required keyword arguments, but no keyword arguments were provided", called_from)
44
46
  end
45
47
 
46
48
  required_kwargs.each do |required_kwarg|
@@ -51,7 +53,7 @@ module DSLCompose
51
53
  # left with only the optional args
52
54
  all_kwargs.delete required_kwarg.name
53
55
  else
54
- raise MissingRequiredArgumentsError, "The required kwarg `#{required_kwarg.name}` was not provided"
56
+ raise MissingRequiredArgumentsError.new("The required kwarg `#{required_kwarg.name}` was not provided", called_from)
55
57
  end
56
58
  end
57
59
 
@@ -61,12 +63,12 @@ module DSLCompose
61
63
 
62
64
  # assert that a value is provided for every required argument
63
65
  unless required_argument_count == required_args.count
64
- raise MissingRequiredArgumentsError, "This requires #{required_non_kwarg_argument_count} arguments, but only #{required_args.count} were provided"
66
+ raise MissingRequiredArgumentsError.new("This requires #{required_non_kwarg_argument_count} arguments, but only #{required_args.count} were provided", called_from)
65
67
  end
66
68
 
67
69
  # assert that too many arguments have not been provided
68
70
  if args.count > required_argument_count + (has_optional_arguments ? 1 : 0)
69
- raise TooManyArgumentsError, "Too many arguments provided"
71
+ raise TooManyArgumentsError.new("Too many arguments provided", called_from)
70
72
  end
71
73
 
72
74
  # Assume all optonal arguments are their defaults (except booleans, which default to false).
@@ -88,7 +90,7 @@ module DSLCompose
88
90
  # asset that, if provided, then the optional argument (always the last one) is a Hash
89
91
  if has_optional_arguments && !optional_arg.nil?
90
92
  unless optional_arg.is_a? Hash
91
- raise OptionalArgumentsShouldBeHashError, "If provided, then the optional arguments must be last, and be represented as a Hash"
93
+ raise OptionalArgumentsShouldBeHashError.new("If provided, then the optional arguments must be last, and be represented as a Hash", called_from)
92
94
  end
93
95
 
94
96
  # assert the each provided optional argument is valid
@@ -110,7 +112,7 @@ module DSLCompose
110
112
  end
111
113
 
112
114
  if optional_arg_value.is_a?(Array) && !optional_argument.array
113
- raise ArrayNotValidError, "An array was provided to an argument which does not accept an array of values"
115
+ raise ArrayNotValidError.new("An array was provided to an argument which does not accept an array of values", called_from)
114
116
  end
115
117
 
116
118
  # to simplify the code, we always process the reset of the validations as an array, even
@@ -121,38 +123,38 @@ module DSLCompose
121
123
  case optional_argument.type
122
124
  when :integer
123
125
  unless value.is_a? Integer
124
- raise InvalidArgumentTypeError, "`#{value}` is not an Integer"
126
+ raise InvalidArgumentTypeError.new("`#{value}` is not an Integer", called_from)
125
127
  end
126
128
  optional_argument.validate_integer! value
127
129
 
128
130
  when :float
129
131
  # float allows either floats or integers
130
132
  unless value.is_a?(Float) || value.is_a?(Integer)
131
- raise InvalidArgumentTypeError, "`#{value}` is not an Float or Integer"
133
+ raise InvalidArgumentTypeError.new("`#{value}` is not an Float or Integer", called_from)
132
134
  end
133
135
  optional_argument.validate_float! value
134
136
 
135
137
  when :symbol
136
138
  unless value.is_a? Symbol
137
- raise InvalidArgumentTypeError, "`#{value}` is not a Symbol"
139
+ raise InvalidArgumentTypeError.new("`#{value}` is not a Symbol", called_from)
138
140
  end
139
141
  optional_argument.validate_symbol! value
140
142
 
141
143
  when :string
142
144
  unless value.is_a? String
143
- raise InvalidArgumentTypeError, "`#{value}` is not a String"
145
+ raise InvalidArgumentTypeError.new("`#{value}` is not a String", called_from)
144
146
  end
145
147
  optional_argument.validate_string! value
146
148
 
147
149
  when :boolean
148
150
  unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
149
- raise InvalidArgumentTypeError, "`#{value}` is not a boolean"
151
+ raise InvalidArgumentTypeError.new("`#{value}` is not a boolean", called_from)
150
152
  end
151
153
  optional_argument.validate_boolean! value
152
154
 
153
155
  when :class
154
156
  unless value.is_a?(ClassCoerce)
155
- raise InvalidArgumentTypeError, "`#{value}` is not a class coerce (String)"
157
+ raise InvalidArgumentTypeError.new("`#{value}` is not a class coerce (String)", called_from)
156
158
  end
157
159
  optional_argument.validate_class! value
158
160
 
@@ -160,7 +162,7 @@ module DSLCompose
160
162
  optional_argument.validate_object! value
161
163
 
162
164
  else
163
- raise InvalidArgumentTypeError, "The argument value `#{value}` is not a supported type"
165
+ raise InvalidArgumentTypeError.new("The argument value `#{value}` is not a supported type", called_from)
164
166
  end
165
167
  end
166
168
 
@@ -174,7 +176,7 @@ module DSLCompose
174
176
  optional_arg_value
175
177
  end
176
178
  rescue => e
177
- raise e, "Error processing optional argument #{optional_argument_name}: #{e.message}", e.backtrace
179
+ raise e, "Error processing optional argument #{optional_argument_name}\n#{e.message}", e.backtrace
178
180
  end
179
181
 
180
182
  end
@@ -200,7 +202,7 @@ module DSLCompose
200
202
  end
201
203
 
202
204
  if required_arg_value.is_a?(Array) && !required_argument.array
203
- raise ArrayNotValidError, "An array was provided to an argument which does not accept an array of values"
205
+ raise ArrayNotValidError.new("An array was provided to an argument which does not accept an array of values", called_from)
204
206
  end
205
207
 
206
208
  # to simplify the code, we always process the reset of the validations as an array, even
@@ -211,38 +213,38 @@ module DSLCompose
211
213
  case required_argument.type
212
214
  when :integer
213
215
  unless value.is_a? Integer
214
- raise InvalidArgumentTypeError, "`#{value}` is not an Integer"
216
+ raise InvalidArgumentTypeError.new("`#{value}` is not an Integer", called_from)
215
217
  end
216
218
  required_argument.validate_integer! value
217
219
 
218
220
  when :float
219
221
  # float allows either floats or integers
220
222
  unless value.is_a?(Float) || value.is_a?(Integer)
221
- raise InvalidArgumentTypeError, "`#{value}` is not an Float or Integer"
223
+ raise InvalidArgumentTypeError.new("`#{value}` is not an Float or Integer", called_from)
222
224
  end
223
225
  required_argument.validate_float! value
224
226
 
225
227
  when :symbol
226
228
  unless value.is_a? Symbol
227
- raise InvalidArgumentTypeError, "`#{value}` is not a Symbol"
229
+ raise InvalidArgumentTypeError.new("`#{value}` is not a Symbol", called_from)
228
230
  end
229
231
  required_argument.validate_symbol! value
230
232
 
231
233
  when :string
232
234
  unless value.is_a? String
233
- raise InvalidArgumentTypeError, "`#{value}` is not a String"
235
+ raise InvalidArgumentTypeError.new("`#{value}` is not a String", called_from)
234
236
  end
235
237
  required_argument.validate_string! value
236
238
 
237
239
  when :boolean
238
240
  unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
239
- raise InvalidArgumentTypeError, "`#{value}` is not a boolean"
241
+ raise InvalidArgumentTypeError.new("`#{value}` is not a boolean", called_from)
240
242
  end
241
243
  required_argument.validate_boolean! value
242
244
 
243
245
  when :class
244
246
  unless value.is_a?(ClassCoerce)
245
- raise InvalidArgumentTypeError, "`#{value}` is not a class coerce (String)"
247
+ raise InvalidArgumentTypeError.new("`#{value}` is not a class coerce (String)", called_from)
246
248
  end
247
249
  required_argument.validate_class! value
248
250
 
@@ -250,7 +252,7 @@ module DSLCompose
250
252
  required_argument.validate_object! value
251
253
 
252
254
  else
253
- raise InvalidArgumentTypeError, "The argument `#{value}` is not a supported type"
255
+ raise InvalidArgumentTypeError.new("The argument `#{value}` is not a supported type", called_from)
254
256
  end
255
257
  end
256
258
 
@@ -264,7 +266,7 @@ module DSLCompose
264
266
  required_arg_value
265
267
  end
266
268
  rescue => e
267
- raise e, "Error processing required argument #{argument_name}: #{e.message}", e.backtrace
269
+ raise e, "Error processing required argument #{argument_name}\n#{e.message}", e.backtrace
268
270
  end
269
271
  end
270
272
 
@@ -5,15 +5,17 @@ module DSLCompose
5
5
  class Execution
6
6
  class MethodCalls
7
7
  class MethodCall
8
- class InvalidDescriptionError < StandardError
8
+ class InvalidDescriptionError < InterpreterError
9
9
  end
10
10
 
11
11
  attr_reader :dsl_method
12
+ attr_reader :called_from
12
13
  attr_reader :arguments
13
14
 
14
- def initialize dsl_method, *args, &block
15
+ def initialize dsl_method, called_from, *args, &block
15
16
  @dsl_method = dsl_method
16
- @arguments = Arguments.new(dsl_method.arguments, *args)
17
+ @called_from = called_from
18
+ @arguments = Arguments.new(dsl_method.arguments, called_from, *args)
17
19
  end
18
20
 
19
21
  def method_name
@@ -30,7 +32,7 @@ module DSLCompose
30
32
  # generate documentation
31
33
  def add_parser_usage_note note
32
34
  unless note.is_a?(String) && note.strip.length > 0
33
- raise InvalidDescriptionError, "The parser usage description `#{note}` is invalid, it must be of type string and have length greater than 0"
35
+ raise InvalidDescriptionError.new("The parser usage description `#{note}` is invalid, it must be of type string and have length greater than 0", @called_from)
34
36
  end
35
37
 
36
38
  @parser_usage_notes ||= []
@@ -14,16 +14,18 @@ module DSLCompose
14
14
  @method_calls.filter { |mc| mc.method_name == method_name }.any?
15
15
  end
16
16
 
17
- def add_method_call(dsl_method, ...)
17
+ def add_method_call(dsl_method, called_from, ...)
18
18
  # make sure we always have a variable which can be used in the exception message
19
+ # set to nil first, so that if we get an exception while setting them
20
+ # it wont break the error message generation
19
21
  dsl_method_name = nil
20
22
  dsl_method_name = dsl_method.name
21
23
 
22
- method_call = MethodCall.new(dsl_method, ...)
24
+ method_call = MethodCall.new(dsl_method, called_from, ...)
23
25
  @method_calls << method_call
24
26
  method_call
25
27
  rescue => e
26
- raise e, "Error while executing method #{dsl_method_name}: #{e.message}", e.backtrace
28
+ raise e, "Error while executing method #{dsl_method_name}\n#{e.message}", e.backtrace
27
29
  end
28
30
 
29
31
  def method_calls_by_name method_name
@@ -3,26 +3,28 @@
3
3
  module DSLCompose
4
4
  class Interpreter
5
5
  class Execution
6
- class MethodIsUniqueError < StandardError
6
+ class MethodIsUniqueError < InterpreterError
7
7
  end
8
8
 
9
- class RequiredMethodNotCalledError < StandardError
9
+ class RequiredMethodNotCalledError < InterpreterError
10
10
  end
11
11
 
12
- class InvalidDescriptionError < StandardError
12
+ class InvalidDescriptionError < InterpreterError
13
13
  end
14
14
 
15
15
  attr_reader :dsl
16
+ attr_reader :called_from
16
17
  attr_reader :klass
17
18
  attr_reader :method_calls
18
19
  attr_reader :arguments
19
20
 
20
21
  # execute/process a dynamically defined DSL
21
- def initialize klass, dsl, *args, &block
22
+ def initialize klass, dsl, called_from, *args, &block
22
23
  @klass = klass
23
24
  @dsl = dsl
25
+ @called_from = called_from
24
26
  @method_calls = MethodCalls.new
25
- @arguments = Arguments.new(dsl.arguments, *args)
27
+ @arguments = Arguments.new(dsl.arguments, called_from, *args)
26
28
 
27
29
  # dynamically process the DSL by calling the provided block
28
30
  # all methods executions will be caught and processed by the method_missing method below
@@ -34,7 +36,7 @@ module DSLCompose
34
36
  dsl.required_dsl_methods.each do |dsl_method|
35
37
  unless @method_calls.method_called? dsl_method.name
36
38
  dsl_method_name = dsl_method&.name
37
- raise RequiredMethodNotCalledError, "The method #{dsl_method_name} is required, but was not called within this DSL"
39
+ raise RequiredMethodNotCalledError.new("The method #{dsl_method_name} is required, but was not called within this DSL", called_from)
38
40
  end
39
41
  end
40
42
  end
@@ -43,7 +45,7 @@ module DSLCompose
43
45
  # generate documentation
44
46
  def add_parser_usage_note note
45
47
  unless note.is_a?(String) && note.strip.length > 0
46
- raise InvalidDescriptionError, "The parser usage description `#{note}` is invalid, it must be of type string and have length greater than 0"
48
+ raise InvalidDescriptionError.new("The parser usage description `#{note}` is invalid, it must be of type string and have length greater than 0", called_from)
47
49
  end
48
50
 
49
51
  @parser_usage_notes ||= []
@@ -60,15 +62,17 @@ module DSLCompose
60
62
 
61
63
  # catch and process any method calls within the DSL block
62
64
  def method_missing(method_name, ...)
65
+ called_from = caller(1..1).first
66
+
63
67
  # if the method does not exist, then this will raise a MethodDoesNotExistError
64
68
  dsl_method = @dsl.dsl_method method_name
65
69
 
66
70
  # if the method is unique, then it can only be called once per DSL
67
71
  if dsl_method.unique? && @method_calls.method_called?(method_name)
68
- raise MethodIsUniqueError, "This method `#{method_name}` is unique and can only be called once within this DSL"
72
+ raise MethodIsUniqueError.new("This method `#{method_name}` is unique and can only be called once within this DSL", called_from)
69
73
  end
70
74
 
71
- @method_calls.add_method_call(dsl_method, ...)
75
+ @method_calls.add_method_call(dsl_method, called_from, ...)
72
76
  end
73
77
 
74
78
  def respond_to_missing?(method_name, *args)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DSLCompose
4
+ class Interpreter
5
+ class InterpreterError < StandardError
6
+ attr_reader :original_context
7
+
8
+ def initialize(message, original_context)
9
+ super(message)
10
+ @original_context = original_context
11
+ end
12
+
13
+ def to_s
14
+ "#{super}\ndsl source: #{@original_context}"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -4,10 +4,7 @@ module DSLCompose
4
4
  # The class is reponsible for parsing and executing a dynamic DSL (dynamic DSLs are
5
5
  # created using the DSLCompose::DSL class).
6
6
  class Interpreter
7
- class DSLExecutionNotFoundError < StandardError
8
- end
9
-
10
- class InvalidDescriptionError < StandardError
7
+ class InvalidDescriptionError < InterpreterError
11
8
  end
12
9
 
13
10
  # A dynamic DSL can be used multiple times on the same class, each time the DSL is used
@@ -23,7 +20,7 @@ module DSLCompose
23
20
  # generate documentation
24
21
  def add_parser_usage_note child_class, note
25
22
  unless note.is_a?(String) && note.strip.length > 0
26
- raise InvalidDescriptionError, "The parser usage description `#{note}` is invalid, it must be of type string and have length greater than 0"
23
+ raise InvalidDescriptionError.new("The parser usage description `#{note}` is invalid, it must be of type string and have length greater than 0", called_from)
27
24
  end
28
25
  @parser_usage_notes ||= {}
29
26
  @parser_usage_notes[child_class] ||= []
@@ -40,20 +37,23 @@ module DSLCompose
40
37
  # Execute/process a dynamically defined DSL on a class.
41
38
  # `klass` is the class in which the DSL is being used, not
42
39
  # the class in which the DSL was defined.
43
- def execute_dsl(klass, dsl, ...)
40
+ def execute_dsl(klass, dsl, called_from, ...)
44
41
  # make sure we have these variables for the exception message below
42
+ # set to nil first, so that if we get an exception while setting them
43
+ # it wont break the error message generation
45
44
  class_name = nil
46
- class_name = klass.name
47
45
  dsl_name = nil
46
+ class_name = klass.name
48
47
  dsl_name = dsl.name
49
48
 
50
- execution = Execution.new(klass, dsl, ...)
49
+ execution = Execution.new(klass, dsl, called_from, ...)
51
50
  @executions << execution
52
51
  execution
53
52
  rescue => e
54
- raise e, "Error processing dsl #{dsl_name} for class #{class_name}: #{e.message}", e.backtrace
53
+ raise e, "Error while defining DSL #{dsl_name} for class #{class_name}:\n#{e.message}", e.backtrace
55
54
  end
56
55
 
56
+ #
57
57
  # Returns an array of all executions for a given class.
58
58
  def class_executions klass
59
59
  @executions.filter { |e| e.klass == klass }
@@ -21,13 +21,13 @@ module DSLCompose
21
21
  "#{child_class.name.split("::").count}_#{has_descendants(child_class) ? 0 : 1}_#{child_class.name}"
22
22
  end
23
23
  # then by ansestory chain (i.e. ancestors before descendants)
24
- extending_classes.sort do |a, b|
24
+ extending_classes.sort! do |a, b|
25
25
  if a < b
26
26
  1
27
27
  elsif a > b
28
28
  -1
29
29
  else
30
- 0
30
+ a.name <=> b.name
31
31
  end
32
32
  end
33
33
 
@@ -28,6 +28,8 @@ module DSLCompose
28
28
  @dsl_execution = dsl_execution
29
29
  @method_names = method_names
30
30
 
31
+ dsl_name = dsl_execution.dsl.name
32
+
31
33
  # assert that a block was provided
32
34
  unless block
33
35
  raise NoBlockProvided
@@ -100,6 +102,14 @@ module DSLCompose
100
102
 
101
103
  # yeild the block in the context of this class
102
104
  instance_exec(**args, &block)
105
+ rescue => e
106
+ # if this is an InterpreterError, then it already has the called_from metadata
107
+ # just continue raising the original error
108
+ if e.is_a? Interpreter::InterpreterError
109
+ raise
110
+ end
111
+ # otherwise, decorate the error with where the DSL was defined
112
+ raise e, "#{e.message}\nparsing class: #{child_class.name}\ndsl name: #{dsl_name}\ndsl method name: #{method_name}\ndsl source: #{method_call.called_from}", e.backtrace
103
113
  end
104
114
  end
105
115
  end
@@ -108,6 +108,14 @@ module DSLCompose
108
108
  @dsl_execution = dsl_execution
109
109
  # yield the block in the context of this class
110
110
  instance_exec(**args, &block)
111
+ rescue => e
112
+ # if this is an InterpreterError, then it already has the called_from metadata
113
+ # just continue raising the original error
114
+ if e.is_a? Interpreter::InterpreterError
115
+ raise
116
+ end
117
+ # otherwise, decorate the error with where the DSL was defined
118
+ raise e, "#{e.message}\nparsing class: #{child_class.name}\ndsl name: #{dsl_name}\ndsl source: #{dsl_execution.called_from}", e.backtrace
111
119
  end
112
120
  end
113
121
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DSLCompose
4
- VERSION = "2.15.1"
4
+ VERSION = "2.15.4"
5
5
  end
data/lib/dsl_compose.rb CHANGED
@@ -34,6 +34,7 @@ require "dsl_compose/reader/execution_reader/arguments_reader"
34
34
 
35
35
  require "dsl_compose/reader_base"
36
36
 
37
+ require "dsl_compose/interpreter/interpreter_error"
37
38
  require "dsl_compose/interpreter/execution/method_calls/method_call"
38
39
  require "dsl_compose/interpreter/execution/method_calls"
39
40
  require "dsl_compose/interpreter/execution/arguments"
@@ -4,23 +4,24 @@ module DSLCompose
4
4
  class Execution
5
5
  class Arguments
6
6
  attr_reader arguments: Hash[untyped, untyped]
7
- def initialize: (untyped arguments, *untyped args) -> void
7
+ attr_reader called_from: String
8
+
9
+ def initialize: (untyped arguments, String called_from, *untyped args) -> void
8
10
  def to_h: -> Hash[untyped, untyped]
9
11
 
10
- class MissingRequiredArgumentsError < StandardError
11
- def initialize: (untyped required_count, untyped provided_count) -> void
12
+ class MissingRequiredArgumentsError < InterpreterError
12
13
  end
13
14
 
14
- class TooManyArgumentsError < StandardError
15
+ class TooManyArgumentsError < InterpreterError
15
16
  end
16
17
 
17
- class OptionalArgumentsShouldBeHashError < StandardError
18
+ class OptionalArgumentsShouldBeHashError < InterpreterError
18
19
  end
19
20
 
20
- class InvalidArgumentTypeError < StandardError
21
+ class InvalidArgumentTypeError < InterpreterError
21
22
  end
22
23
 
23
- class ArrayNotValidError < StandardError
24
+ class ArrayNotValidError < InterpreterError
24
25
  end
25
26
  end
26
27
  end
@@ -4,21 +4,22 @@ module DSLCompose
4
4
  class Execution
5
5
  class MethodCalls
6
6
  class MethodCall
7
- class InvalidDescriptionError < StandardError
8
- end
9
-
10
7
  @method_call: MethodCall
11
8
  @parser_usage_notes: Array[String]
12
9
 
13
10
  attr_reader dsl_method: DSL::DSLMethod
11
+ attr_reader called_from: String
14
12
  attr_reader arguments: Arguments
15
13
 
16
- def initialize: (DSL::DSLMethod dsl_method, *untyped args) -> void
14
+ def initialize: (DSL::DSLMethod dsl_method, String called_from, *untyped args) -> void
17
15
  def method_name: -> Symbol
18
16
  def add_parser_usage_note: (String note) -> void
19
17
  def parser_usage_notes: () -> Array[String]
20
18
 
21
19
  def to_h: -> Hash[untyped, untyped]
20
+
21
+ class InvalidDescriptionError < InterpreterError
22
+ end
22
23
  end
23
24
  end
24
25
  end
@@ -9,7 +9,7 @@ module DSLCompose
9
9
  def method_calls: () -> Array[MethodCall]
10
10
  def method_called?: (Symbol method_name) -> bool
11
11
  def method_calls_by_name: (Symbol method_name) -> Array[MethodCall]
12
- def add_method_call: (DSL::DSLMethod dsl_method, *untyped args) -> MethodCall
12
+ def add_method_call: (DSL::DSLMethod dsl_method, String called_from, *untyped args) -> MethodCall
13
13
  end
14
14
  end
15
15
  end
@@ -5,11 +5,12 @@ module DSLCompose
5
5
  @parser_usage_notes: Array[String]
6
6
 
7
7
  attr_reader dsl: DSL
8
+ attr_reader called_from: String
8
9
  attr_reader klass: Object
9
10
  attr_reader method_calls: MethodCalls
10
11
  attr_reader arguments: Arguments
11
12
 
12
- def initialize: (Object klass, DSL dsl, *untyped args) -> void
13
+ def initialize: (Object klass, DSL dsl, String called_from, *untyped args) -> void
13
14
  def instance_eval: () -> void
14
15
  def add_parser_usage_note: (String note) -> void
15
16
  def parser_usage_notes: () -> Array[String]
@@ -18,11 +19,15 @@ module DSLCompose
18
19
  def method_missing: (Symbol method_name, *untyped args) -> untyped
19
20
  def respond_to_missing?: (Symbol method_name, *untyped args) -> untyped
20
21
 
21
- class MethodIsUniqueError < StandardError
22
+ class MethodIsUniqueError < InterpreterError
22
23
  end
23
24
 
24
- class RequiredMethodNotCalledError < StandardError
25
+ class RequiredMethodNotCalledError < InterpreterError
25
26
  end
27
+
28
+ class InvalidDescriptionError < InterpreterError
29
+ end
30
+
26
31
  end
27
32
  end
28
33
  end
@@ -0,0 +1,11 @@
1
+
2
+ # Classes
3
+ module DSLCompose
4
+ class Interpreter
5
+ class InterpreterError < StandardError
6
+ attr_reader original_context: String
7
+ def initialize: (String message, String original_context) -> void
8
+ def to_s: -> String
9
+ end
10
+ end
11
+ end
@@ -12,10 +12,7 @@ module DSLCompose
12
12
  def add_parser_usage_note: (singleton(Object) klass, String note) -> void
13
13
  def parser_usage_notes: (singleton(Object) klass) -> Array[String]
14
14
 
15
- class InvalidDescriptionError < StandardError
16
- end
17
-
18
- class DSLExecutionNotFoundError < StandardError
15
+ class InvalidDescriptionError < InterpreterError
19
16
  end
20
17
  end
21
18
  end
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: 2.15.1
4
+ version: 2.15.4
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-10-03 00:00:00.000000000 Z
11
+ date: 2023-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: class_spec_helper
@@ -67,6 +67,7 @@ files:
67
67
  - lib/dsl_compose/interpreter/execution/arguments.rb
68
68
  - lib/dsl_compose/interpreter/execution/method_calls.rb
69
69
  - lib/dsl_compose/interpreter/execution/method_calls/method_call.rb
70
+ - lib/dsl_compose/interpreter/interpreter_error.rb
70
71
  - lib/dsl_compose/parser.rb
71
72
  - lib/dsl_compose/parser/block_arguments.rb
72
73
  - lib/dsl_compose/parser/for_children_of_parser.rb
@@ -109,6 +110,7 @@ files:
109
110
  - sig/dsl_compose/interpreter/execution/arguments.rbs
110
111
  - sig/dsl_compose/interpreter/execution/method_calls.rbs
111
112
  - sig/dsl_compose/interpreter/execution/method_calls/method_call.rbs
113
+ - sig/dsl_compose/interpreter/interpreter_error.rbs
112
114
  - sig/dsl_compose/parser.rbs
113
115
  - sig/dsl_compose/parser/block_arguments.rbs
114
116
  - sig/dsl_compose/parser/for_children_of_parser.rbs