• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

localstack / localstack / 19558051963

20 Nov 2025 05:48PM UTC coverage: 86.859% (-0.05%) from 86.907%
19558051963

push

github

web-flow
Sns:v2 publish (#13399)

199 of 279 new or added lines in 5 files covered. (71.33%)

168 existing lines in 9 files now uncovered.

68851 of 79268 relevant lines covered (86.86%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.04
/localstack-core/localstack/services/stepfunctions/asl/parse/preprocessor.py
1
import json
1✔
2
import logging
1✔
3
from typing import Any
1✔
4

5
from antlr4 import ParserRuleContext
1✔
6
from antlr4.tree.Tree import ParseTree, TerminalNodeImpl
1✔
7

8
from localstack.services.stepfunctions.asl.antlr.runtime.ASLLexer import ASLLexer
1✔
9
from localstack.services.stepfunctions.asl.antlr.runtime.ASLParser import ASLParser
1✔
10
from localstack.services.stepfunctions.asl.antlr.runtime.ASLParserVisitor import (
1✔
11
    ASLParserVisitor,
12
)
13
from localstack.services.stepfunctions.asl.antlt4utils.antlr4utils import (
1✔
14
    from_string_literal,
15
    is_production,
16
    is_terminal,
17
)
18
from localstack.services.stepfunctions.asl.component.common.assign.assign_decl import (
1✔
19
    AssignDecl,
20
)
21
from localstack.services.stepfunctions.asl.component.common.assign.assign_decl_binding import (
1✔
22
    AssignDeclBinding,
23
)
24
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_binding import (
1✔
25
    AssignTemplateBinding,
26
    AssignTemplateBindingStringExpressionSimple,
27
    AssignTemplateBindingValue,
28
)
29
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_value import (
1✔
30
    AssignTemplateValue,
31
)
32
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_value_array import (
1✔
33
    AssignTemplateValueArray,
34
)
35
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_value_object import (
1✔
36
    AssignTemplateValueObject,
37
)
38
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_value_terminal import (
1✔
39
    AssignTemplateValueTerminal,
40
    AssignTemplateValueTerminalLit,
41
    AssignTemplateValueTerminalStringJSONata,
42
)
43
from localstack.services.stepfunctions.asl.component.common.catch.catch_decl import (
1✔
44
    CatchDecl,
45
)
46
from localstack.services.stepfunctions.asl.component.common.catch.catcher_decl import (
1✔
47
    CatcherDecl,
48
)
49
from localstack.services.stepfunctions.asl.component.common.catch.catcher_props import (
1✔
50
    CatcherProps,
51
)
52
from localstack.services.stepfunctions.asl.component.common.comment import Comment
1✔
53
from localstack.services.stepfunctions.asl.component.common.error_name.custom_error_name import (
1✔
54
    CustomErrorName,
55
)
56
from localstack.services.stepfunctions.asl.component.common.error_name.error_equals_decl import (
1✔
57
    ErrorEqualsDecl,
58
)
59
from localstack.services.stepfunctions.asl.component.common.error_name.error_name import (
1✔
60
    ErrorName,
61
)
62
from localstack.services.stepfunctions.asl.component.common.error_name.states_error_name import (
1✔
63
    StatesErrorName,
64
)
65
from localstack.services.stepfunctions.asl.component.common.error_name.states_error_name_type import (
1✔
66
    StatesErrorNameType,
67
)
68
from localstack.services.stepfunctions.asl.component.common.flow.end import End
1✔
69
from localstack.services.stepfunctions.asl.component.common.flow.next import Next
1✔
70
from localstack.services.stepfunctions.asl.component.common.flow.start_at import StartAt
1✔
71
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_binding import (
1✔
72
    JSONataTemplateBinding,
73
)
74
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_value import (
1✔
75
    JSONataTemplateValue,
76
)
77
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_value_array import (
1✔
78
    JSONataTemplateValueArray,
79
)
80
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_value_object import (
1✔
81
    JSONataTemplateValueObject,
82
)
83
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_value_terminal import (
1✔
84
    JSONataTemplateValueTerminalLit,
85
    JSONataTemplateValueTerminalStringJSONata,
86
)
87
from localstack.services.stepfunctions.asl.component.common.outputdecl import Output
1✔
88
from localstack.services.stepfunctions.asl.component.common.parargs import (
1✔
89
    ArgumentsJSONataTemplateValueObject,
90
    ArgumentsStringJSONata,
91
    Parameters,
92
    Parargs,
93
)
94
from localstack.services.stepfunctions.asl.component.common.path.input_path import (
1✔
95
    InputPath,
96
)
97
from localstack.services.stepfunctions.asl.component.common.path.items_path import (
1✔
98
    ItemsPath,
99
)
100
from localstack.services.stepfunctions.asl.component.common.path.output_path import (
1✔
101
    OutputPath,
102
)
103
from localstack.services.stepfunctions.asl.component.common.path.result_path import (
1✔
104
    ResultPath,
105
)
106
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payload_value import (
1✔
107
    PayloadValue,
108
)
109
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadarr.payload_arr import (
1✔
110
    PayloadArr,
111
)
112
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadbinding.payload_binding import (
1✔
113
    PayloadBinding,
114
    PayloadBindingStringExpressionSimple,
115
    PayloadBindingValue,
116
)
117
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadtmpl.payload_tmpl import (
1✔
118
    PayloadTmpl,
119
)
120
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_bool import (
1✔
121
    PayloadValueBool,
122
)
123
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_float import (
1✔
124
    PayloadValueFloat,
125
)
126
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_int import (
1✔
127
    PayloadValueInt,
128
)
129
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_null import (
1✔
130
    PayloadValueNull,
131
)
132
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_str import (
1✔
133
    PayloadValueStr,
134
)
135
from localstack.services.stepfunctions.asl.component.common.query_language import (
1✔
136
    QueryLanguage,
137
    QueryLanguageMode,
138
)
139
from localstack.services.stepfunctions.asl.component.common.result_selector import (
1✔
140
    ResultSelector,
141
)
142
from localstack.services.stepfunctions.asl.component.common.retry.backoff_rate_decl import (
1✔
143
    BackoffRateDecl,
144
)
145
from localstack.services.stepfunctions.asl.component.common.retry.interval_seconds_decl import (
1✔
146
    IntervalSecondsDecl,
147
)
148
from localstack.services.stepfunctions.asl.component.common.retry.jitter_strategy_decl import (
1✔
149
    JitterStrategy,
150
    JitterStrategyDecl,
151
)
152
from localstack.services.stepfunctions.asl.component.common.retry.max_attempts_decl import (
1✔
153
    MaxAttemptsDecl,
154
)
155
from localstack.services.stepfunctions.asl.component.common.retry.max_delay_seconds_decl import (
1✔
156
    MaxDelaySecondsDecl,
157
)
158
from localstack.services.stepfunctions.asl.component.common.retry.retrier_decl import (
1✔
159
    RetrierDecl,
160
)
161
from localstack.services.stepfunctions.asl.component.common.retry.retrier_props import (
1✔
162
    RetrierProps,
163
)
164
from localstack.services.stepfunctions.asl.component.common.retry.retry_decl import (
1✔
165
    RetryDecl,
166
)
167
from localstack.services.stepfunctions.asl.component.common.string.string_expression import (
1✔
168
    StringContextPath,
169
    StringExpression,
170
    StringExpressionSimple,
171
    StringIntrinsicFunction,
172
    StringJSONata,
173
    StringJsonPath,
174
    StringLiteral,
175
    StringSampler,
176
    StringVariableSample,
177
)
178
from localstack.services.stepfunctions.asl.component.common.timeouts.heartbeat import (
1✔
179
    HeartbeatSeconds,
180
    HeartbeatSecondsJSONata,
181
    HeartbeatSecondsPath,
182
)
183
from localstack.services.stepfunctions.asl.component.common.timeouts.timeout import (
1✔
184
    TimeoutSeconds,
185
    TimeoutSecondsJSONata,
186
    TimeoutSecondsPath,
187
)
188
from localstack.services.stepfunctions.asl.component.component import Component
1✔
189
from localstack.services.stepfunctions.asl.component.program.program import Program
1✔
190
from localstack.services.stepfunctions.asl.component.program.states import States
1✔
191
from localstack.services.stepfunctions.asl.component.program.version import Version
1✔
192
from localstack.services.stepfunctions.asl.component.state.state import CommonStateField
1✔
193
from localstack.services.stepfunctions.asl.component.state.state_choice.choice_rule import (
1✔
194
    ChoiceRule,
195
)
196
from localstack.services.stepfunctions.asl.component.state.state_choice.choices_decl import (
1✔
197
    ChoicesDecl,
198
)
199
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison import (
1✔
200
    ComparisonComposite,
201
    ComparisonCompositeAnd,
202
    ComparisonCompositeNot,
203
    ComparisonCompositeOr,
204
    ComparisonCompositeProps,
205
    ConditionJSONataLit,
206
    ConditionStringJSONata,
207
)
208
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison_func import (
1✔
209
    ComparisonFunc,
210
    ComparisonFuncStringVariableSample,
211
    ComparisonFuncValue,
212
)
213
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison_operator_type import (
1✔
214
    ComparisonOperatorType,
215
)
216
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison_type import (
1✔
217
    Comparison,
218
)
219
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison_variable import (
1✔
220
    ComparisonVariable,
221
)
222
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.variable import (
1✔
223
    Variable,
224
)
225
from localstack.services.stepfunctions.asl.component.state.state_choice.default_decl import (
1✔
226
    DefaultDecl,
227
)
228
from localstack.services.stepfunctions.asl.component.state.state_choice.state_choice import (
1✔
229
    StateChoice,
230
)
231
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.execution_type import (
1✔
232
    ExecutionType,
233
)
234
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.item_reader_decl import (
1✔
235
    ItemReader,
236
)
237
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.csv_header_location import (
1✔
238
    CSVHeaderLocation,
239
)
240
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.csv_headers import (
1✔
241
    CSVHeaders,
242
)
243
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.input_type import (
1✔
244
    InputType,
245
)
246
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.max_items_decl import (
1✔
247
    MaxItemsDecl,
248
    MaxItemsInt,
249
    MaxItemsPath,
250
    MaxItemsStringJSONata,
251
)
252
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.reader_config_decl import (
1✔
253
    ReaderConfig,
254
)
255
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.reader_config_props import (
1✔
256
    ReaderConfigProps,
257
)
258
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_selector import (
1✔
259
    ItemSelector,
260
)
261
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.items.items import (
1✔
262
    ItemsArray,
263
    ItemsJSONata,
264
)
265
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.iteration.itemprocessor.item_processor_decl import (
1✔
266
    ItemProcessorDecl,
267
)
268
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.iteration.itemprocessor.processor_config import (
1✔
269
    ProcessorConfig,
270
)
271
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.iteration.iterator.iterator_decl import (
1✔
272
    IteratorDecl,
273
)
274
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.label import (
1✔
275
    Label,
276
)
277
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.max_concurrency import (
1✔
278
    MaxConcurrency,
279
    MaxConcurrencyJSONata,
280
    MaxConcurrencyPath,
281
)
282
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.mode import (
1✔
283
    Mode,
284
)
285
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.result_writer.result_writer_decl import (
1✔
286
    ResultWriter,
287
)
288
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.state_map import (
1✔
289
    StateMap,
290
)
291
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.tolerated_failure import (
1✔
292
    ToleratedFailureCountInt,
293
    ToleratedFailureCountPath,
294
    ToleratedFailurePercentage,
295
    ToleratedFailurePercentagePath,
296
    ToleratedFailurePercentageStringJSONata,
297
)
298
from localstack.services.stepfunctions.asl.component.state.state_execution.state_parallel.branches_decl import (
1✔
299
    BranchesDecl,
300
)
301
from localstack.services.stepfunctions.asl.component.state.state_execution.state_parallel.state_parallel import (
1✔
302
    StateParallel,
303
)
304
from localstack.services.stepfunctions.asl.component.state.state_execution.state_task.credentials import (
1✔
305
    Credentials,
306
    RoleArn,
307
)
308
from localstack.services.stepfunctions.asl.component.state.state_execution.state_task.service.resource import (
1✔
309
    Resource,
310
)
311
from localstack.services.stepfunctions.asl.component.state.state_execution.state_task.state_task_factory import (
1✔
312
    state_task_for,
313
)
314
from localstack.services.stepfunctions.asl.component.state.state_fail.cause_decl import (
1✔
315
    Cause,
316
    CausePath,
317
)
318
from localstack.services.stepfunctions.asl.component.state.state_fail.error_decl import (
1✔
319
    Error,
320
    ErrorPath,
321
)
322
from localstack.services.stepfunctions.asl.component.state.state_fail.state_fail import (
1✔
323
    StateFail,
324
)
325
from localstack.services.stepfunctions.asl.component.state.state_pass.result import (
1✔
326
    Result,
327
)
328
from localstack.services.stepfunctions.asl.component.state.state_pass.state_pass import (
1✔
329
    StatePass,
330
)
331
from localstack.services.stepfunctions.asl.component.state.state_props import StateProps
1✔
332
from localstack.services.stepfunctions.asl.component.state.state_succeed.state_succeed import (
1✔
333
    StateSucceed,
334
)
335
from localstack.services.stepfunctions.asl.component.state.state_type import StateType
1✔
336
from localstack.services.stepfunctions.asl.component.state.state_wait.state_wait import (
1✔
337
    StateWait,
338
)
339
from localstack.services.stepfunctions.asl.component.state.state_wait.wait_function.seconds import (
1✔
340
    Seconds,
341
    SecondsJSONata,
342
)
343
from localstack.services.stepfunctions.asl.component.state.state_wait.wait_function.seconds_path import (
1✔
344
    SecondsPath,
345
)
346
from localstack.services.stepfunctions.asl.component.state.state_wait.wait_function.timestamp import (
1✔
347
    Timestamp,
348
    TimestampPath,
349
)
350
from localstack.services.stepfunctions.asl.parse.intrinsic.intrinsic_parser import (
1✔
351
    IntrinsicParser,
352
)
353
from localstack.services.stepfunctions.asl.parse.typed_props import TypedProps
1✔
354

355
LOG = logging.getLogger(__name__)
1✔
356

357

358
class Preprocessor(ASLParserVisitor):
1✔
359
    def __init__(self):
1✔
360
        self._query_language_per_scope: list[QueryLanguage] = []
1✔
361

362
    def _get_current_query_language(self) -> QueryLanguage:
1✔
363
        return self._query_language_per_scope[-1]
1✔
364

365
    def _get_top_level_query_language(self) -> QueryLanguage:
1✔
366
        return self._query_language_per_scope[0]
1✔
367

368
    def _open_query_language_scope(self, parse_tree: ParseTree) -> None:
1✔
369
        production = is_production(parse_tree)
1✔
370
        if production is None:
1✔
UNCOV
371
            raise RuntimeError(f"Cannot expect QueryLanguage definition at depth: {parse_tree}")
×
372

373
        # Extract the QueryLanguage declaration at this ParseTree level, if any.
374
        query_language = None
1✔
375
        for child in production.children:
1✔
376
            sub_production = is_production(child, ASLParser.RULE_top_layer_stmt) or is_production(
1✔
377
                child, ASLParser.RULE_state_stmt
378
            )
379
            if sub_production is not None:
1✔
380
                child = sub_production.children[0]
1✔
381
            sub_production = is_production(child, ASLParser.RULE_query_language_decl)
1✔
382
            if sub_production is not None:
1✔
383
                query_language = self.visit(sub_production)
1✔
384
                break
1✔
385

386
        # Check this is the initial scope, if so set the initial value to the declaration or the default.
387
        if not self._query_language_per_scope:
1✔
388
            if query_language is None:
1✔
389
                query_language = QueryLanguage()
1✔
390
        # Otherwise, check for logical conflicts and add the latest or inherited value to as the next scope.
391
        else:
392
            top_query_language = self._get_top_level_query_language()
1✔
393
            if query_language is None:
1✔
394
                query_language = top_query_language
1✔
395
            if (
1✔
396
                top_query_language.query_language_mode == QueryLanguageMode.JSONata
397
                and query_language.query_language_mode == QueryLanguageMode.JSONPath
398
            ):
399
                raise ValueError(
1✔
400
                    f"Cannot downgrade from JSONata context to a JSONPath context at: {parse_tree}"
401
                )
402

403
        self._query_language_per_scope.append(query_language)
1✔
404

405
    def _close_query_language_scope(self) -> None:
1✔
406
        self._query_language_per_scope.pop()
1✔
407

408
    def _is_query_language(self, query_language_mode: QueryLanguageMode) -> bool:
1✔
409
        current_query_language = self._get_current_query_language()
1✔
410
        return current_query_language.query_language_mode == query_language_mode
1✔
411

412
    def _raise_if_query_language_is_not(
1✔
413
        self, query_language_mode: QueryLanguageMode, ctx: ParserRuleContext
414
    ) -> None:
415
        if not self._is_query_language(query_language_mode=query_language_mode):
1✔
416
            raise ValueError(
1✔
417
                f"Unsupported declaration in QueryLanguage={query_language_mode} block: {ctx.getText()}"
418
            )
419

420
    @staticmethod
1✔
421
    def _inner_string_of(parser_rule_context: ParserRuleContext) -> str | None:
1✔
422
        if is_terminal(parser_rule_context, ASLLexer.NULL):
1✔
423
            return None
1✔
424
        inner_str = parser_rule_context.getText()
1✔
425
        if inner_str.startswith('"') and inner_str.endswith('"'):
1✔
426
            inner_str = inner_str[1:-1]
1✔
427
        return inner_str
1✔
428

429
    def _inner_jsonata_expr(self, ctx: ParserRuleContext) -> str:
1✔
430
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
431
        inner_string_value = from_string_literal(parser_rule_context=ctx)
1✔
432
        # Strip the start and end jsonata symbols {%<body>%}
433
        expression_body = inner_string_value[2:-2]
1✔
434
        # Often leading and trailing spaces are used around the body: remove.
435
        expression = expression_body.strip()
1✔
436
        return expression
1✔
437

438
    def visitComment_decl(self, ctx: ASLParser.Comment_declContext) -> Comment:
1✔
439
        inner_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
440
        return Comment(comment=inner_str)
1✔
441

442
    def visitVersion_decl(self, ctx: ASLParser.Version_declContext) -> Version:
1✔
443
        version_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
444
        return Version(version=version_str)
1✔
445

446
    def visitStartat_decl(self, ctx: ASLParser.Startat_declContext) -> StartAt:
1✔
447
        inner_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
448
        return StartAt(start_at_name=inner_str)
1✔
449

450
    def visitStates_decl(self, ctx: ASLParser.States_declContext) -> States:
1✔
451
        states = States()
1✔
452
        for child in ctx.children:
1✔
453
            cmp: Component | None = self.visit(child)
1✔
454
            if isinstance(cmp, CommonStateField):
1✔
455
                # TODO move check to setter or checker layer?
456
                if cmp.name in states.states:
1✔
UNCOV
457
                    raise ValueError(f"State redefinition {child.getText()}")
×
458
                states.states[cmp.name] = cmp
1✔
459
        return states
1✔
460

461
    def visitType_decl(self, ctx: ASLParser.Type_declContext) -> StateType:
1✔
462
        return self.visit(ctx.state_type())
1✔
463

464
    def visitState_type(self, ctx: ASLParser.State_typeContext) -> StateType:
1✔
465
        state_type: int = ctx.children[0].symbol.type
1✔
466
        return StateType(state_type)
1✔
467

468
    def visitResource_decl(self, ctx: ASLParser.Resource_declContext) -> Resource:
1✔
469
        inner_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
470
        return Resource.from_resource_arn(inner_str)
1✔
471

472
    def visitEnd_decl(self, ctx: ASLParser.End_declContext) -> End:
1✔
473
        bool_child: ParseTree = ctx.children[-1]
1✔
474
        bool_term: TerminalNodeImpl | None = is_terminal(bool_child)
1✔
475
        if bool_term is None:
1✔
UNCOV
476
            raise ValueError(f"Could not derive End from declaration context '{ctx.getText()}'")
×
477
        bool_term_rule: int = bool_term.getSymbol().type
1✔
478
        is_end = bool_term_rule == ASLLexer.TRUE
1✔
479
        return End(is_end=is_end)
1✔
480

481
    def visitNext_decl(self, ctx: ASLParser.Next_declContext) -> Next:
1✔
482
        inner_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
483
        return Next(name=inner_str)
1✔
484

485
    def visitResult_path_decl(self, ctx: ASLParser.Result_path_declContext) -> ResultPath:
1✔
486
        self._raise_if_query_language_is_not(
1✔
487
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
488
        )
489
        inner_str = self._inner_string_of(parser_rule_context=ctx.children[-1])
1✔
490
        return ResultPath(result_path_src=inner_str)
1✔
491

492
    def visitInput_path_decl(self, ctx: ASLParser.Input_path_declContext) -> InputPath:
1✔
493
        string_sampler: StringSampler | None = None
1✔
494
        if not is_terminal(pt=ctx.children[-1], token_type=ASLLexer.NULL):
1✔
495
            string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
496
        return InputPath(string_sampler=string_sampler)
1✔
497

498
    def visitOutput_path_decl(self, ctx: ASLParser.Output_path_declContext) -> OutputPath:
1✔
499
        self._raise_if_query_language_is_not(
1✔
500
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
501
        )
502
        string_sampler: StringSampler | None = None
1✔
503
        if is_production(ctx.children[-1], ASLParser.RULE_string_sampler):
1✔
504
            string_sampler: StringSampler = self.visitString_sampler(ctx.children[-1])
1✔
505
        return OutputPath(string_sampler=string_sampler)
1✔
506

507
    def visitResult_decl(self, ctx: ASLParser.Result_declContext) -> Result:
1✔
508
        json_decl = ctx.json_value_decl()
1✔
509
        json_str: str = json_decl.getText()
1✔
510
        json_obj: json = json.loads(json_str)
1✔
511
        return Result(result_obj=json_obj)
1✔
512

513
    def visitParameters_decl(self, ctx: ASLParser.Parameters_declContext) -> Parameters:
1✔
514
        self._raise_if_query_language_is_not(
1✔
515
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
516
        )
517
        payload_tmpl: PayloadTmpl = self.visit(ctx.payload_tmpl_decl())
1✔
518
        return Parameters(payload_tmpl=payload_tmpl)
1✔
519

520
    def visitTimeout_seconds_int(self, ctx: ASLParser.Timeout_seconds_intContext) -> TimeoutSeconds:
1✔
521
        seconds = int(ctx.INT().getText())
1✔
522
        return TimeoutSeconds(timeout_seconds=seconds)
1✔
523

524
    def visitTimeout_seconds_jsonata(
1✔
525
        self, ctx: ASLParser.Timeout_seconds_jsonataContext
526
    ) -> TimeoutSecondsJSONata:
UNCOV
527
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
×
UNCOV
528
        return TimeoutSecondsJSONata(string_jsonata=string_jsonata)
×
529

530
    def visitTimeout_seconds_path(
1✔
531
        self, ctx: ASLParser.Timeout_seconds_pathContext
532
    ) -> TimeoutSecondsPath:
533
        self._raise_if_query_language_is_not(
1✔
534
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
535
        )
536
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
537
        return TimeoutSecondsPath(string_sampler=string_sampler)
1✔
538

539
    def visitHeartbeat_seconds_int(
1✔
540
        self, ctx: ASLParser.Heartbeat_seconds_intContext
541
    ) -> HeartbeatSeconds:
542
        seconds = int(ctx.INT().getText())
1✔
543
        return HeartbeatSeconds(heartbeat_seconds=seconds)
1✔
544

545
    def visitHeartbeat_seconds_jsonata(
1✔
546
        self, ctx: ASLParser.Heartbeat_seconds_jsonataContext
547
    ) -> HeartbeatSecondsJSONata:
548
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
549
        return HeartbeatSecondsJSONata(string_jsonata=string_jsonata)
1✔
550

551
    def visitHeartbeat_seconds_path(
1✔
552
        self, ctx: ASLParser.Heartbeat_seconds_pathContext
553
    ) -> HeartbeatSecondsPath:
554
        self._raise_if_query_language_is_not(
1✔
555
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
556
        )
557
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
558
        return HeartbeatSecondsPath(string_sampler=string_sampler)
1✔
559

560
    def visitResult_selector_decl(
1✔
561
        self, ctx: ASLParser.Result_selector_declContext
562
    ) -> ResultSelector:
563
        self._raise_if_query_language_is_not(
1✔
564
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
565
        )
566
        payload_tmpl: PayloadTmpl = self.visit(ctx.payload_tmpl_decl())
1✔
567
        return ResultSelector(payload_tmpl=payload_tmpl)
1✔
568

569
    def visitBranches_decl(self, ctx: ASLParser.Branches_declContext) -> BranchesDecl:
1✔
570
        programs: list[Program] = []
1✔
571
        for child in ctx.children:
1✔
572
            cmp: Component | None = self.visit(child)
1✔
573
            if isinstance(cmp, Program):
1✔
574
                programs.append(cmp)
1✔
575
        return BranchesDecl(programs=programs)
1✔
576

577
    def visitState_decl_body(self, ctx: ASLParser.State_decl_bodyContext) -> StateProps:
1✔
578
        self._open_query_language_scope(ctx)
1✔
579
        state_props = StateProps()
1✔
580
        for child in ctx.children:
1✔
581
            cmp: Component | None = self.visit(child)
1✔
582
            state_props.add(cmp)
1✔
583
        if state_props.get(QueryLanguage) is None:
1✔
584
            state_props.add(self._get_current_query_language())
1✔
585
        self._close_query_language_scope()
1✔
586
        return state_props
1✔
587

588
    def visitState_decl(self, ctx: ASLParser.State_declContext) -> CommonStateField:
1✔
589
        state_name = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
590
        state_props: StateProps = self.visit(ctx.state_decl_body())
1✔
591
        state_props.name = state_name
1✔
592
        common_state_field = self._common_state_field_of(state_props=state_props)
1✔
593
        return common_state_field
1✔
594

595
    @staticmethod
1✔
596
    def _common_state_field_of(state_props: StateProps) -> CommonStateField:
1✔
597
        # TODO: use subtype loading strategy.
598
        match state_props.get(StateType):
1✔
599
            case StateType.Task:
1✔
600
                resource: Resource = state_props.get(Resource)
1✔
601
                state = state_task_for(resource)
1✔
602
            case StateType.Pass:
1✔
603
                state = StatePass()
1✔
604
            case StateType.Choice:
1✔
605
                state = StateChoice()
1✔
606
            case StateType.Fail:
1✔
607
                state = StateFail()
1✔
608
            case StateType.Succeed:
1✔
609
                state = StateSucceed()
1✔
610
            case StateType.Wait:
1✔
611
                state = StateWait()
1✔
612
            case StateType.Map:
1✔
613
                state = StateMap()
1✔
614
            case StateType.Parallel:
1✔
615
                state = StateParallel()
1✔
616
            case None:
×
UNCOV
617
                raise TypeError("No Type declaration for State in context.")
×
UNCOV
618
            case unknown:
×
UNCOV
619
                raise TypeError(
×
620
                    f"Unknown StateType value '{unknown}' in StateProps object in context."  # noqa
621
                )
622
        state.from_state_props(state_props)
1✔
623
        return state
1✔
624

625
    def visitCondition_lit(self, ctx: ASLParser.Condition_litContext) -> ConditionJSONataLit:
1✔
626
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
627
        bool_child: ParseTree = ctx.children[-1]
1✔
628
        bool_term: TerminalNodeImpl | None = is_terminal(bool_child)
1✔
629
        if bool_term is None:
1✔
UNCOV
630
            raise ValueError(
×
631
                f"Could not derive boolean literal from declaration context '{ctx.getText()}'."
632
            )
633
        bool_term_rule: int = bool_term.getSymbol().type
1✔
634
        bool_val: bool = bool_term_rule == ASLLexer.TRUE
1✔
635
        return ConditionJSONataLit(literal=bool_val)
1✔
636

637
    def visitCondition_string_jsonata(
1✔
638
        self, ctx: ASLParser.Condition_string_jsonataContext
639
    ) -> ConditionStringJSONata:
640
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx=ctx.string_jsonata())
1✔
641
        return ConditionStringJSONata(string_jsonata=string_jsonata)
1✔
642

643
    def visitVariable_decl(self, ctx: ASLParser.Variable_declContext) -> Variable:
1✔
644
        self._raise_if_query_language_is_not(
1✔
645
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
646
        )
647
        string_sampler: StringSampler = self.visitString_sampler(ctx=ctx.string_sampler())
1✔
648
        return Variable(string_sampler=string_sampler)
1✔
649

650
    def visitComparison_op(self, ctx: ASLParser.Comparison_opContext) -> ComparisonOperatorType:
1✔
651
        self._raise_if_query_language_is_not(
1✔
652
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
653
        )
654
        try:
1✔
655
            operator_type: int = ctx.children[0].symbol.type
1✔
656
            return ComparisonOperatorType(operator_type)
1✔
UNCOV
657
        except Exception:
×
UNCOV
658
            raise ValueError(f"Could not derive ComparisonOperator from context '{ctx.getText()}'.")
×
659

660
    def visitComparison_func_value(
1✔
661
        self, ctx: ASLParser.Comparison_func_valueContext
662
    ) -> ComparisonFuncValue:
663
        self._raise_if_query_language_is_not(
1✔
664
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
665
        )
666
        comparison_op: ComparisonOperatorType = self.visit(ctx.comparison_op())
1✔
667
        json_decl = ctx.json_value_decl()
1✔
668
        json_str: str = json_decl.getText()
1✔
669
        json_obj: Any = json.loads(json_str)
1✔
670
        return ComparisonFuncValue(operator_type=comparison_op, value=json_obj)
1✔
671

672
    def visitComparison_func_string_variable_sample(
1✔
673
        self, ctx: ASLParser.Comparison_func_string_variable_sampleContext
674
    ) -> ComparisonFuncStringVariableSample:
675
        self._raise_if_query_language_is_not(
1✔
676
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
677
        )
678
        comparison_op: ComparisonOperatorType = self.visit(ctx.comparison_op())
1✔
679
        string_variable_sample: StringVariableSample = self.visitString_variable_sample(
1✔
680
            ctx.string_variable_sample()
681
        )
682
        return ComparisonFuncStringVariableSample(
1✔
683
            operator_type=comparison_op, string_variable_sample=string_variable_sample
684
        )
685

686
    def visitDefault_decl(self, ctx: ASLParser.Default_declContext) -> DefaultDecl:
1✔
687
        state_name = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
688
        return DefaultDecl(state_name=state_name)
1✔
689

690
    def visitChoice_operator(
1✔
691
        self, ctx: ASLParser.Choice_operatorContext
692
    ) -> ComparisonComposite.ChoiceOp:
693
        self._raise_if_query_language_is_not(
1✔
694
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
695
        )
696
        pt: TerminalNodeImpl | None = is_terminal(ctx.children[0])
1✔
697
        if not pt:
1✔
UNCOV
698
            raise ValueError(f"Could not derive ChoiceOperator in block '{ctx.getText()}'.")
×
699
        return ComparisonComposite.ChoiceOp(pt.symbol.type)
1✔
700

701
    def visitComparison_composite(
1✔
702
        self, ctx: ASLParser.Comparison_compositeContext
703
    ) -> ComparisonComposite:
704
        choice_op: ComparisonComposite.ChoiceOp = self.visit(ctx.choice_operator())
1✔
705
        rules: list[ChoiceRule] = []
1✔
706
        for child in ctx.children[1:]:
1✔
707
            cmp: Component | None = self.visit(child)
1✔
708
            if not cmp:
1✔
709
                continue
1✔
710
            elif isinstance(cmp, ChoiceRule):
1✔
711
                rules.append(cmp)
1✔
712

713
        match choice_op:
1✔
714
            case ComparisonComposite.ChoiceOp.Not:
1✔
715
                if len(rules) != 1:
1✔
UNCOV
716
                    raise ValueError(
×
717
                        f"ComparisonCompositeNot must carry only one ComparisonCompositeStmt in: '{ctx.getText()}'."
718
                    )
719
                return ComparisonCompositeNot(rule=rules[0])
1✔
720
            case ComparisonComposite.ChoiceOp.And:
1✔
721
                return ComparisonCompositeAnd(rules=rules)
1✔
UNCOV
722
            case ComparisonComposite.ChoiceOp.Or:
×
UNCOV
723
                return ComparisonCompositeOr(rules=rules)
×
724

725
    def visitChoice_rule_comparison_composite(
1✔
726
        self, ctx: ASLParser.Choice_rule_comparison_compositeContext
727
    ) -> ChoiceRule:
728
        composite_stmts = ComparisonCompositeProps()
1✔
729
        for child in ctx.children:
1✔
730
            cmp: Component | None = self.visit(child)
1✔
731
            composite_stmts.add(cmp)
1✔
732
        return ChoiceRule(
1✔
733
            comparison=composite_stmts.get(
734
                typ=ComparisonComposite,
735
                raise_on_missing=ValueError(
736
                    f"Expecting a 'ComparisonComposite' definition at '{ctx.getText()}'."
737
                ),
738
            ),
739
            next_stmt=composite_stmts.get(Next),
740
            comment=composite_stmts.get(Comment),
741
            assign=composite_stmts.get(AssignDecl),
742
            output=composite_stmts.get(Output),
743
        )
744

745
    def visitChoice_rule_comparison_variable(
1✔
746
        self, ctx: ASLParser.Choice_rule_comparison_variableContext
747
    ) -> ChoiceRule:
748
        comparison_stmts = StateProps()
1✔
749
        for child in ctx.children:
1✔
750
            cmp: Component | None = self.visit(child)
1✔
751
            comparison_stmts.add(cmp)
1✔
752
        if self._is_query_language(query_language_mode=QueryLanguageMode.JSONPath):
1✔
753
            variable: Variable = comparison_stmts.get(
1✔
754
                typ=Variable,
755
                raise_on_missing=ValueError(
756
                    f"Expected a Variable declaration in '{ctx.getText()}'."
757
                ),
758
            )
759
            comparison_func: Comparison = comparison_stmts.get(
1✔
760
                typ=Comparison,
761
                raise_on_missing=ValueError(
762
                    f"Expected a ComparisonFunction declaration in '{ctx.getText()}'."
763
                ),
764
            )
765
            if not isinstance(comparison_func, ComparisonFunc):
1✔
UNCOV
766
                raise ValueError(f"Expected a ComparisonFunction declaration in '{ctx.getText()}'")
×
767
            comparison_variable = ComparisonVariable(variable=variable, func=comparison_func)
1✔
768
            return ChoiceRule(
1✔
769
                comparison=comparison_variable,
770
                next_stmt=comparison_stmts.get(Next),
771
                comment=comparison_stmts.get(Comment),
772
                assign=None,
773
                output=None,
774
            )
775
        else:
776
            condition: Comparison = comparison_stmts.get(
1✔
777
                typ=Comparison,
778
                raise_on_missing=ValueError(
779
                    f"Expected a Condition declaration in '{ctx.getText()}'"
780
                ),
781
            )
782
            return ChoiceRule(
1✔
783
                comparison=condition,
784
                next_stmt=comparison_stmts.get(Next),
785
                comment=comparison_stmts.get(Comment),
786
                assign=comparison_stmts.get(AssignDecl),
787
                output=comparison_stmts.get(Output),
788
            )
789

790
    def visitChoices_decl(self, ctx: ASLParser.Choices_declContext) -> ChoicesDecl:
1✔
791
        rules: list[ChoiceRule] = []
1✔
792
        for child in ctx.children:
1✔
793
            cmp: Component | None = self.visit(child)
1✔
794
            if not cmp:
1✔
795
                continue
1✔
796
            elif isinstance(cmp, ChoiceRule):
1✔
797
                rules.append(cmp)
1✔
798
        return ChoicesDecl(rules=rules)
1✔
799

800
    def visitError(self, ctx: ASLParser.ErrorContext) -> Error:
1✔
801
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
802
        return Error(string_expression=string_expression)
1✔
803

804
    def visitError_path(self, ctx: ASLParser.Error_pathContext) -> ErrorPath:
1✔
805
        self._raise_if_query_language_is_not(
1✔
806
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
807
        )
808
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
809
        return ErrorPath(string_expression=string_expression)
1✔
810

811
    def visitCause(self, ctx: ASLParser.CauseContext) -> Cause:
1✔
812
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
813
        return Cause(string_expression=string_expression)
1✔
814

815
    def visitCause_path(self, ctx: ASLParser.Cause_pathContext) -> CausePath:
1✔
816
        self._raise_if_query_language_is_not(
1✔
817
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
818
        )
819
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
820
        return CausePath(string_expression=string_expression)
1✔
821

822
    def visitRole_arn(self, ctx: ASLParser.Role_arnContext) -> RoleArn:
1✔
823
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
824
        return RoleArn(string_expression=string_expression)
1✔
825

826
    def visitRole_path(self, ctx: ASLParser.Role_pathContext) -> RoleArn:
1✔
827
        self._raise_if_query_language_is_not(
1✔
828
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
829
        )
830
        string_expression_simple: StringExpressionSimple = self.visitString_expression_simple(
1✔
831
            ctx=ctx.string_expression_simple()
832
        )
833
        return RoleArn(string_expression=string_expression_simple)
1✔
834

835
    def visitCredentials_decl(self, ctx: ASLParser.Credentials_declContext) -> Credentials:
1✔
836
        role_arn: RoleArn = self.visit(ctx.role_arn_decl())
1✔
837
        return Credentials(role_arn=role_arn)
1✔
838

839
    def visitSeconds_int(self, ctx: ASLParser.Seconds_intContext) -> Seconds:
1✔
840
        return Seconds(seconds=int(ctx.INT().getText()))
1✔
841

842
    def visitSeconds_jsonata(self, ctx: ASLParser.Seconds_jsonataContext) -> SecondsJSONata:
1✔
843
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
844
        return SecondsJSONata(string_jsonata=string_jsonata)
1✔
845

846
    def visitSeconds_path(self, ctx: ASLParser.Seconds_pathContext) -> SecondsPath:
1✔
847
        self._raise_if_query_language_is_not(
1✔
848
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
849
        )
850
        string_sampler: StringSampler = self.visitString_sampler(ctx=ctx.string_sampler())
1✔
851
        return SecondsPath(string_sampler=string_sampler)
1✔
852

853
    def visitItems_path_decl(self, ctx: ASLParser.Items_path_declContext) -> ItemsPath:
1✔
854
        self._raise_if_query_language_is_not(
1✔
855
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
856
        )
857
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
858
        return ItemsPath(string_sampler=string_sampler)
1✔
859

860
    def visitMax_concurrency_int(self, ctx: ASLParser.Max_concurrency_intContext) -> MaxConcurrency:
1✔
861
        return MaxConcurrency(num=int(ctx.INT().getText()))
1✔
862

863
    def visitMax_concurrency_jsonata(
1✔
864
        self, ctx: ASLParser.Max_concurrency_jsonataContext
865
    ) -> MaxConcurrencyJSONata:
866
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
867
        return MaxConcurrencyJSONata(string_jsonata=string_jsonata)
1✔
868

869
    def visitMax_concurrency_path(
1✔
870
        self, ctx: ASLParser.Max_concurrency_pathContext
871
    ) -> MaxConcurrencyPath:
872
        self._raise_if_query_language_is_not(
1✔
873
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
874
        )
875
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
876
        return MaxConcurrencyPath(string_sampler=string_sampler)
1✔
877

878
    def visitMode_decl(self, ctx: ASLParser.Mode_declContext) -> Mode:
1✔
879
        mode_type: int = self.visit(ctx.mode_type())
1✔
880
        return Mode(mode_type)
1✔
881

882
    def visitMode_type(self, ctx: ASLParser.Mode_typeContext) -> int:
1✔
883
        return ctx.children[0].symbol.type
1✔
884

885
    def visitExecution_decl(self, ctx: ASLParser.Execution_declContext) -> ExecutionType:
1✔
886
        execution_type: int = self.visit(ctx.execution_type())
1✔
887
        return ExecutionType(execution_type)
1✔
888

889
    def visitExecution_type(self, ctx: ASLParser.Execution_typeContext) -> int:
1✔
890
        return ctx.children[0].symbol.type
1✔
891

892
    def visitTimestamp(self, ctx: ASLParser.TimestampContext) -> Timestamp:
1✔
893
        string: StringExpression = self.visit(ctx.children[-1])
1✔
894
        return Timestamp(string=string)
1✔
895

896
    def visitTimestamp_path(self, ctx: ASLParser.Timestamp_pathContext) -> TimestampPath:
1✔
897
        self._raise_if_query_language_is_not(
1✔
898
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
899
        )
900
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
901
        return TimestampPath(string=string_sampler)
1✔
902

903
    def visitProcessor_config_decl(
1✔
904
        self, ctx: ASLParser.Processor_config_declContext
905
    ) -> ProcessorConfig:
906
        props = TypedProps()
1✔
907
        for child in ctx.children:
1✔
908
            cmp = self.visit(child)
1✔
909
            props.add(cmp)
1✔
910
        return ProcessorConfig(
1✔
911
            mode=props.get(typ=Mode) or ProcessorConfig.DEFAULT_MODE,
912
            execution_type=props.get(typ=ExecutionType) or ProcessorConfig.DEFAULT_EXECUTION_TYPE,
913
        )
914

915
    def visitItem_processor_item(self, ctx: ASLParser.Item_processor_itemContext) -> Component:
1✔
916
        return self.visit(ctx.children[0])
1✔
917

918
    def visitItem_processor_decl(
1✔
919
        self, ctx: ASLParser.Item_processor_declContext
920
    ) -> ItemProcessorDecl:
921
        props = TypedProps()
1✔
922
        for child in ctx.children:
1✔
923
            cmp = self.visit(child)
1✔
924
            props.add(cmp)
1✔
925
        return ItemProcessorDecl(
1✔
926
            query_language=props.get(QueryLanguage) or QueryLanguage(),
927
            start_at=props.get(
928
                typ=StartAt,
929
                raise_on_missing=ValueError(
930
                    f"Expected a StartAt declaration at '{ctx.getText()}'."
931
                ),
932
            ),
933
            states=props.get(
934
                typ=States,
935
                raise_on_missing=ValueError(f"Expected a States declaration at '{ctx.getText()}'."),
936
            ),
937
            comment=props.get(typ=Comment),
938
            processor_config=props.get(typ=ProcessorConfig) or ProcessorConfig(),
939
        )
940

941
    def visitIterator_decl(self, ctx: ASLParser.Iterator_declContext) -> IteratorDecl:
1✔
942
        props = TypedProps()
1✔
943
        for child in ctx.children:
1✔
944
            cmp = self.visit(child)
1✔
945
            props.add(cmp)
1✔
946
        return IteratorDecl(
1✔
947
            comment=props.get(typ=Comment),
948
            query_language=self._get_current_query_language(),
949
            start_at=props.get(
950
                typ=StartAt,
951
                raise_on_missing=ValueError(
952
                    f"Expected a StartAt declaration at '{ctx.getText()}'."
953
                ),
954
            ),
955
            states=props.get(
956
                typ=States,
957
                raise_on_missing=ValueError(f"Expected a States declaration at '{ctx.getText()}'."),
958
            ),
959
            processor_config=props.get(typ=ProcessorConfig) or ProcessorConfig(),
960
        )
961

962
    def visitItem_selector_decl(self, ctx: ASLParser.Item_selector_declContext) -> ItemSelector:
1✔
963
        template_value_object = self.visitAssign_template_value_object(
1✔
964
            ctx=ctx.assign_template_value_object()
965
        )
966
        return ItemSelector(template_value_object=template_value_object)
1✔
967

968
    def visitItem_reader_decl(self, ctx: ASLParser.Item_reader_declContext) -> ItemReader:
1✔
969
        props = StateProps()
1✔
970
        for child in ctx.children[3:-1]:
1✔
971
            cmp = self.visit(child)
1✔
972
            props.add(cmp)
1✔
973
        resource: Resource = props.get(
1✔
974
            typ=Resource,
975
            raise_on_missing=ValueError(f"Expected a Resource declaration at '{ctx.getText()}'."),
976
        )
977
        return ItemReader(
1✔
978
            resource=resource,
979
            parargs=props.get(Parargs),
980
            reader_config=props.get(ReaderConfig),
981
        )
982

983
    def visitReader_config_decl(self, ctx: ASLParser.Reader_config_declContext) -> ReaderConfig:
1✔
984
        props = ReaderConfigProps()
1✔
985
        for child in ctx.children:
1✔
986
            cmp = self.visit(child)
1✔
987
            props.add(cmp)
1✔
988
        return ReaderConfig(
1✔
989
            input_type=props.get(
990
                typ=InputType,
991
                raise_on_missing=ValueError(
992
                    f"Expected a InputType declaration at '{ctx.getText()}'."
993
                ),
994
            ),
995
            max_items_decl=props.get(typ=MaxItemsDecl),
996
            csv_header_location=props.get(CSVHeaderLocation),
997
            csv_headers=props.get(CSVHeaders),
998
        )
999

1000
    def visitInput_type_decl(self, ctx: ASLParser.Input_type_declContext) -> InputType:
1✔
1001
        input_type = self._inner_string_of(ctx.string_literal())
1✔
1002
        return InputType(input_type=input_type)
1✔
1003

1004
    def visitCsv_header_location_decl(
1✔
1005
        self, ctx: ASLParser.Csv_header_location_declContext
1006
    ) -> CSVHeaderLocation:
1007
        value = self._inner_string_of(ctx.string_literal())
1✔
1008
        return CSVHeaderLocation(csv_header_location_value=value)
1✔
1009

1010
    def visitCsv_headers_decl(self, ctx: ASLParser.Csv_headers_declContext) -> CSVHeaders:
1✔
1011
        csv_headers: list[str] = []
1✔
1012
        for child in ctx.children[3:-1]:
1✔
1013
            maybe_str = is_production(pt=child, rule_index=ASLParser.RULE_string_literal)
1✔
1014
            if maybe_str is not None:
1✔
1015
                csv_headers.append(self._inner_string_of(maybe_str))
1✔
1016
        # TODO: check for empty headers behaviour.
1017
        return CSVHeaders(header_names=csv_headers)
1✔
1018

1019
    def visitMax_items_path(self, ctx: ASLParser.Max_items_pathContext) -> MaxItemsPath:
1✔
1020
        self._raise_if_query_language_is_not(
1✔
1021
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
1022
        )
1023
        string_sampler: StringSampler = self.visitString_sampler(ctx=ctx.string_sampler())
1✔
1024
        return MaxItemsPath(string_sampler=string_sampler)
1✔
1025

1026
    def visitMax_items_int(self, ctx: ASLParser.Max_items_intContext) -> MaxItemsInt:
1✔
1027
        return MaxItemsInt(max_items=int(ctx.INT().getText()))
1✔
1028

1029
    def visitMax_items_string_jsonata(
1✔
1030
        self, ctx: ASLParser.Max_items_string_jsonataContext
1031
    ) -> MaxItemsStringJSONata:
1032
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
1033
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
1034
        return MaxItemsStringJSONata(string_jsonata=string_jsonata)
1✔
1035

1036
    def visitTolerated_failure_count_int(
1✔
1037
        self, ctx: ASLParser.Tolerated_failure_count_intContext
1038
    ) -> ToleratedFailureCountInt:
1039
        LOG.warning(
1✔
1040
            "ToleratedFailureCount declarations currently have no effect on the program evaluation."
1041
        )
1042
        count = int(ctx.INT().getText())
1✔
1043
        return ToleratedFailureCountInt(tolerated_failure_count=count)
1✔
1044

1045
    def visitTolerated_failure_count_string_jsonata(
1✔
1046
        self, ctx: ASLParser.Tolerated_failure_count_string_jsonataContext
1047
    ) -> ToleratedFailurePercentageStringJSONata:
1048
        LOG.warning(
1✔
1049
            "ToleratedFailureCount declarations currently have no effect on the program evaluation."
1050
        )
1051
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx=ctx.string_jsonata())
1✔
1052
        return ToleratedFailurePercentageStringJSONata(string_jsonata=string_jsonata)
1✔
1053

1054
    def visitTolerated_failure_count_path(
1✔
1055
        self, ctx: ASLParser.Tolerated_failure_count_pathContext
1056
    ) -> ToleratedFailureCountPath:
1057
        self._raise_if_query_language_is_not(
1✔
1058
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
1059
        )
1060
        LOG.warning(
1✔
1061
            "ToleratedFailureCountPath declarations currently have no effect on the program evaluation."
1062
        )
1063
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
1064
        return ToleratedFailureCountPath(string_sampler=string_sampler)
1✔
1065

1066
    def visitTolerated_failure_percentage_number(
1✔
1067
        self, ctx: ASLParser.Tolerated_failure_percentage_numberContext
1068
    ) -> ToleratedFailurePercentage:
1069
        LOG.warning(
1✔
1070
            "ToleratedFailurePercentage declarations currently have no effect on the program evaluation."
1071
        )
1072
        percentage = float(ctx.NUMBER().getText())
1✔
1073
        return ToleratedFailurePercentage(tolerated_failure_percentage=percentage)
1✔
1074

1075
    def visitTolerated_failure_percentage_string_jsonata(
1✔
1076
        self, ctx: ASLParser.Tolerated_failure_percentage_string_jsonataContext
1077
    ) -> ToleratedFailurePercentageStringJSONata:
1078
        LOG.warning(
1✔
1079
            "ToleratedFailurePercentage declarations currently have no effect on the program evaluation."
1080
        )
1081
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx=ctx.string_jsonata())
1✔
1082
        return ToleratedFailurePercentageStringJSONata(string_jsonata=string_jsonata)
1✔
1083

1084
    def visitTolerated_failure_percentage_path(
1✔
1085
        self, ctx: ASLParser.Tolerated_failure_percentage_pathContext
1086
    ) -> ToleratedFailurePercentagePath:
1087
        self._raise_if_query_language_is_not(
1✔
1088
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
1089
        )
1090
        LOG.warning(
1✔
1091
            "ToleratedFailurePercentagePath declarations currently have no effect on the program evaluation."
1092
        )
1093
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
1094
        return ToleratedFailurePercentagePath(string_sampler=string_sampler)
1✔
1095

1096
    def visitLabel_decl(self, ctx: ASLParser.Label_declContext) -> Label:
1✔
1097
        label = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
1098
        return Label(label=label)
1✔
1099

1100
    def visitResult_writer_decl(self, ctx: ASLParser.Result_writer_declContext) -> ResultWriter:
1✔
1101
        props = StateProps()
1✔
1102
        for child in ctx.children[3:-1]:
1✔
1103
            cmp = self.visit(child)
1✔
1104
            props.add(cmp)
1✔
1105
        resource: Resource = props.get(
1✔
1106
            typ=Resource,
1107
            raise_on_missing=ValueError(f"Expected a Resource declaration at '{ctx.getText()}'."),
1108
        )
1109
        # TODO: add tests for arguments in jsonata blocks using result writer
1110
        parargs: Parargs = props.get(
1✔
1111
            typ=Parargs,
1112
            raise_on_missing=ValueError(
1113
                f"Expected a Parameters/Arguments declaration at '{ctx.getText()}'."
1114
            ),
1115
        )
1116
        return ResultWriter(resource=resource, parargs=parargs)
1✔
1117

1118
    def visitRetry_decl(self, ctx: ASLParser.Retry_declContext) -> RetryDecl:
1✔
1119
        retriers: list[RetrierDecl] = []
1✔
1120
        for child in ctx.children:
1✔
1121
            cmp: Component | None = self.visit(child)
1✔
1122
            if isinstance(cmp, RetrierDecl):
1✔
1123
                retriers.append(cmp)
1✔
1124
        return RetryDecl(retriers=retriers)
1✔
1125

1126
    def visitRetrier_decl(self, ctx: ASLParser.Retrier_declContext) -> RetrierDecl:
1✔
1127
        props = RetrierProps()
1✔
1128
        for child in ctx.children:
1✔
1129
            cmp: Component | None = self.visit(child)
1✔
1130
            props.add(cmp)
1✔
1131
        return RetrierDecl.from_retrier_props(props=props)
1✔
1132

1133
    def visitRetrier_stmt(self, ctx: ASLParser.Retrier_stmtContext):
1✔
1134
        return self.visit(ctx.children[0])
1✔
1135

1136
    def visitError_equals_decl(self, ctx: ASLParser.Error_equals_declContext) -> ErrorEqualsDecl:
1✔
1137
        error_names: list[ErrorName] = []
1✔
1138
        for child in ctx.children:
1✔
1139
            cmp = self.visit(child)
1✔
1140
            if isinstance(cmp, ErrorName):
1✔
1141
                error_names.append(cmp)
1✔
1142
        return ErrorEqualsDecl(error_names=error_names)
1✔
1143

1144
    def visitError_name(self, ctx: ASLParser.Error_nameContext) -> ErrorName:
1✔
1145
        pt = ctx.children[0]
1✔
1146

1147
        # Case: StatesErrorName.
1148
        prc: ParserRuleContext | None = is_production(
1✔
1149
            pt=pt, rule_index=ASLParser.RULE_states_error_name
1150
        )
1151
        if prc:
1✔
1152
            return self.visit(prc)
1✔
1153

1154
        # Case CustomErrorName.
1155
        error_name = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
1156
        return CustomErrorName(error_name=error_name)
1✔
1157

1158
    def visitStates_error_name(self, ctx: ASLParser.States_error_nameContext) -> StatesErrorName:
1✔
1159
        pt: TerminalNodeImpl | None = is_terminal(ctx.children[0])
1✔
1160
        if not pt:
1✔
UNCOV
1161
            raise ValueError(f"Could not derive ErrorName in block '{ctx.getText()}'.")
×
1162
        states_error_name_type = StatesErrorNameType(pt.symbol.type)
1✔
1163
        return StatesErrorName(states_error_name_type)
1✔
1164

1165
    def visitInterval_seconds_decl(
1✔
1166
        self, ctx: ASLParser.Interval_seconds_declContext
1167
    ) -> IntervalSecondsDecl:
1168
        return IntervalSecondsDecl(seconds=int(ctx.INT().getText()))
1✔
1169

1170
    def visitMax_attempts_decl(self, ctx: ASLParser.Max_attempts_declContext) -> MaxAttemptsDecl:
1✔
1171
        return MaxAttemptsDecl(attempts=int(ctx.INT().getText()))
1✔
1172

1173
    def visitBackoff_rate_decl(self, ctx: ASLParser.Backoff_rate_declContext) -> BackoffRateDecl:
1✔
1174
        return BackoffRateDecl(rate=float(ctx.children[-1].getText()))
1✔
1175

1176
    def visitMax_delay_seconds_decl(
1✔
1177
        self, ctx: ASLParser.Max_delay_seconds_declContext
1178
    ) -> MaxDelaySecondsDecl:
1179
        return MaxDelaySecondsDecl(max_delays_seconds=int(ctx.INT().getText()))
1✔
1180

1181
    def visitJitter_strategy_decl(
1✔
1182
        self, ctx: ASLParser.Jitter_strategy_declContext
1183
    ) -> JitterStrategyDecl:
1184
        last_child: ParseTree = ctx.children[-1]
1✔
1185
        strategy_child: TerminalNodeImpl | None = is_terminal(last_child)
1✔
1186
        strategy_value = strategy_child.getSymbol().type
1✔
1187
        jitter_strategy = JitterStrategy(strategy_value)
1✔
1188
        return JitterStrategyDecl(jitter_strategy=jitter_strategy)
1✔
1189

1190
    def visitCatch_decl(self, ctx: ASLParser.Catch_declContext) -> CatchDecl:
1✔
1191
        catchers: list[CatcherDecl] = []
1✔
1192
        for child in ctx.children:
1✔
1193
            cmp: Component | None = self.visit(child)
1✔
1194
            if isinstance(cmp, CatcherDecl):
1✔
1195
                catchers.append(cmp)
1✔
1196
        return CatchDecl(catchers=catchers)
1✔
1197

1198
    def visitCatcher_decl(self, ctx: ASLParser.Catcher_declContext) -> CatcherDecl:
1✔
1199
        props = CatcherProps()
1✔
1200
        for child in ctx.children:
1✔
1201
            cmp: Component | None = self.visit(child)
1✔
1202
            props.add(cmp)
1✔
1203
        if self._is_query_language(QueryLanguageMode.JSONPath) and not props.get(ResultPath):
1✔
1204
            props.add(CatcherDecl.DEFAULT_RESULT_PATH)
1✔
1205
        return CatcherDecl.from_catcher_props(props=props)
1✔
1206

1207
    def visitPayload_value_float(
1✔
1208
        self, ctx: ASLParser.Payload_value_floatContext
1209
    ) -> PayloadValueFloat:
UNCOV
1210
        return PayloadValueFloat(val=float(ctx.NUMBER().getText()))
×
1211

1212
    def visitPayload_value_int(self, ctx: ASLParser.Payload_value_intContext) -> PayloadValueInt:
1✔
1213
        return PayloadValueInt(val=int(ctx.INT().getText()))
1✔
1214

1215
    def visitPayload_value_bool(self, ctx: ASLParser.Payload_value_boolContext) -> PayloadValueBool:
1✔
1216
        bool_child: ParseTree = ctx.children[0]
1✔
1217
        bool_term: TerminalNodeImpl | None = is_terminal(bool_child)
1✔
1218
        if bool_term is None:
1✔
UNCOV
1219
            raise ValueError(
×
1220
                f"Could not derive PayloadValueBool from declaration context '{ctx.getText()}'."
1221
            )
1222
        bool_term_rule: int = bool_term.getSymbol().type
1✔
1223
        bool_val: bool = bool_term_rule == ASLLexer.TRUE
1✔
1224
        return PayloadValueBool(val=bool_val)
1✔
1225

1226
    def visitPayload_value_null(self, ctx: ASLParser.Payload_value_nullContext) -> PayloadValueNull:
1✔
UNCOV
1227
        return PayloadValueNull()
×
1228

1229
    def visitPayload_value_str(self, ctx: ASLParser.Payload_value_strContext) -> PayloadValueStr:
1✔
1230
        string_literal: StringLiteral = self.visitString_literal(ctx=ctx.string_literal())
1✔
1231
        return PayloadValueStr(val=string_literal.literal_value)
1✔
1232

1233
    def visitPayload_binding_sample(
1✔
1234
        self, ctx: ASLParser.Payload_binding_sampleContext
1235
    ) -> PayloadBindingStringExpressionSimple:
1236
        string_dollar: str = self._inner_string_of(parser_rule_context=ctx.STRINGDOLLAR())
1✔
1237
        field = string_dollar[:-2]
1✔
1238
        string_expression_simple: StringExpressionSimple = self.visitString_expression_simple(
1✔
1239
            ctx.string_expression_simple()
1240
        )
1241
        return PayloadBindingStringExpressionSimple(
1✔
1242
            field=field, string_expression_simple=string_expression_simple
1243
        )
1244

1245
    def visitPayload_binding_value(
1✔
1246
        self, ctx: ASLParser.Payload_binding_valueContext
1247
    ) -> PayloadBindingValue:
1248
        string_literal: StringLiteral = self.visitString_literal(ctx=ctx.string_literal())
1✔
1249
        payload_value: PayloadValue = self.visit(ctx.payload_value_decl())
1✔
1250
        return PayloadBindingValue(field=string_literal.literal_value, payload_value=payload_value)
1✔
1251

1252
    def visitPayload_arr_decl(self, ctx: ASLParser.Payload_arr_declContext) -> PayloadArr:
1✔
1253
        payload_values: list[PayloadValue] = []
1✔
1254
        for child in ctx.children:
1✔
1255
            cmp: Component | None = self.visit(child)
1✔
1256
            if isinstance(cmp, PayloadValue):
1✔
1257
                payload_values.append(cmp)
1✔
1258
        return PayloadArr(payload_values=payload_values)
1✔
1259

1260
    def visitPayload_tmpl_decl(self, ctx: ASLParser.Payload_tmpl_declContext) -> PayloadTmpl:
1✔
1261
        payload_bindings: list[PayloadBinding] = []
1✔
1262
        for child in ctx.children:
1✔
1263
            cmp: Component | None = self.visit(child)
1✔
1264
            if isinstance(cmp, PayloadBinding):
1✔
1265
                payload_bindings.append(cmp)
1✔
1266
        return PayloadTmpl(payload_bindings=payload_bindings)
1✔
1267

1268
    def visitPayload_value_decl(self, ctx: ASLParser.Payload_value_declContext) -> PayloadValue:
1✔
1269
        value = ctx.children[0]
1✔
1270
        return self.visit(value)
1✔
1271

1272
    def visitProgram_decl(self, ctx: ASLParser.Program_declContext) -> Program:
1✔
1273
        self._open_query_language_scope(ctx)
1✔
1274
        props = TypedProps()
1✔
1275
        for child in ctx.children:
1✔
1276
            cmp: Component | None = self.visit(child)
1✔
1277
            props.add(cmp)
1✔
1278
        if props.get(QueryLanguage) is None:
1✔
1279
            props.add(self._get_current_query_language())
1✔
1280
        program = Program(
1✔
1281
            query_language=props.get(typ=QueryLanguage) or QueryLanguage(),
1282
            start_at=props.get(
1283
                typ=StartAt,
1284
                raise_on_missing=ValueError(
1285
                    f"No '{StartAt}' definition for Program in context: '{ctx.getText()}'."
1286
                ),
1287
            ),
1288
            states=props.get(
1289
                typ=States,
1290
                raise_on_missing=ValueError(
1291
                    f"No '{States}' definition for Program in context: '{ctx.getText()}'."
1292
                ),
1293
            ),
1294
            timeout_seconds=props.get(TimeoutSeconds),
1295
            comment=props.get(typ=Comment),
1296
            version=props.get(typ=Version),
1297
        )
1298
        self._close_query_language_scope()
1✔
1299
        return program
1✔
1300

1301
    def visitState_machine(self, ctx: ASLParser.State_machineContext) -> Program:
1✔
1302
        return self.visit(ctx.program_decl())
1✔
1303

1304
    def visitQuery_language_decl(self, ctx: ASLParser.Query_language_declContext) -> QueryLanguage:
1✔
1305
        query_language_mode_int = ctx.children[-1].getSymbol().type
1✔
1306
        query_language_mode = QueryLanguageMode(value=query_language_mode_int)
1✔
1307
        return QueryLanguage(query_language_mode=query_language_mode)
1✔
1308

1309
    def visitAssign_template_value_terminal_float(
1✔
1310
        self, ctx: ASLParser.Assign_template_value_terminal_floatContext
1311
    ) -> AssignTemplateValueTerminalLit:
1312
        float_value = float(ctx.NUMBER().getText())
1✔
1313
        return AssignTemplateValueTerminalLit(value=float_value)
1✔
1314

1315
    def visitAssign_template_value_terminal_int(
1✔
1316
        self, ctx: ASLParser.Assign_template_value_terminal_intContext
1317
    ) -> AssignTemplateValueTerminalLit:
1318
        int_value = int(ctx.INT().getText())
1✔
1319
        return AssignTemplateValueTerminalLit(value=int_value)
1✔
1320

1321
    def visitAssign_template_value_terminal_bool(
1✔
1322
        self, ctx: ASLParser.Assign_template_value_terminal_boolContext
1323
    ) -> AssignTemplateValueTerminalLit:
1324
        bool_term_rule: int = ctx.children[0].getSymbol().type
1✔
1325
        bool_value: bool = bool_term_rule == ASLLexer.TRUE
1✔
1326
        return AssignTemplateValueTerminalLit(value=bool_value)
1✔
1327

1328
    def visitAssign_template_value_terminal_null(
1✔
1329
        self, ctx: ASLParser.Assign_template_value_terminal_nullContext
1330
    ) -> AssignTemplateValueTerminalLit:
1331
        return AssignTemplateValueTerminalLit(value=None)
1✔
1332

1333
    def visitAssign_template_value_terminal_string_jsonata(
1✔
1334
        self, ctx: ASLParser.Assign_template_value_terminal_string_jsonataContext
1335
    ) -> AssignTemplateValueTerminal:
1336
        # Return a JSONata expression resolver or a suppressed depending on the current language mode.
1337
        current_query_language = self._get_current_query_language()
1✔
1338
        if current_query_language.query_language_mode == QueryLanguageMode.JSONata:
1✔
1339
            string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
1340
            return AssignTemplateValueTerminalStringJSONata(string_jsonata=string_jsonata)
1✔
1341
        else:
1342
            inner_string_value = self._inner_string_of(parser_rule_context=ctx.string_jsonata())
1✔
1343
            return AssignTemplateValueTerminalLit(value=inner_string_value)
1✔
1344

1345
    def visitAssign_template_value_terminal_string_literal(
1✔
1346
        self, ctx: ASLParser.Assign_template_value_terminal_string_literalContext
1347
    ) -> AssignTemplateValueTerminal:
1348
        string_literal = self._inner_string_of(ctx.string_literal())
1✔
1349
        return AssignTemplateValueTerminalLit(value=string_literal)
1✔
1350

1351
    def visitAssign_template_value(self, ctx: ASLParser.Assign_template_valueContext):
1✔
1352
        return self.visit(ctx.children[0])
1✔
1353

1354
    def visitAssign_template_value_array(
1✔
1355
        self, ctx: ASLParser.Assign_template_value_arrayContext
1356
    ) -> AssignTemplateValueArray:
1357
        values: list[AssignTemplateValue] = []
1✔
1358
        for child in ctx.children:
1✔
1359
            cmp: Component | None = self.visit(child)
1✔
1360
            if isinstance(cmp, AssignTemplateValue):
1✔
1361
                values.append(cmp)
1✔
1362
        return AssignTemplateValueArray(values=values)
1✔
1363

1364
    def visitAssign_template_value_object(
1✔
1365
        self, ctx: ASLParser.Assign_template_value_objectContext
1366
    ) -> AssignTemplateValueObject:
1367
        bindings: list[AssignTemplateBinding] = []
1✔
1368
        for child in ctx.children:
1✔
1369
            cmp: Component | None = self.visit(child)
1✔
1370
            if isinstance(cmp, AssignTemplateBinding):
1✔
1371
                bindings.append(cmp)
1✔
1372
        return AssignTemplateValueObject(bindings=bindings)
1✔
1373

1374
    def visitAssign_template_binding_value(
1✔
1375
        self, ctx: ASLParser.Assign_template_binding_valueContext
1376
    ) -> AssignTemplateBindingValue:
1377
        string_literal: StringLiteral = self.visitString_literal(ctx=ctx.string_literal())
1✔
1378
        assign_value: AssignTemplateValue = self.visit(ctx.assign_template_value())
1✔
1379
        return AssignTemplateBindingValue(
1✔
1380
            identifier=string_literal.literal_value, assign_value=assign_value
1381
        )
1382

1383
    def visitAssign_template_binding_string_expression_simple(
1✔
1384
        self, ctx: ASLParser.Assign_template_binding_string_expression_simpleContext
1385
    ) -> AssignTemplateBindingStringExpressionSimple:
1386
        identifier: str = self._inner_string_of(ctx.STRINGDOLLAR())
1✔
1387
        identifier = identifier[:-2]
1✔
1388
        string_expression_simple: StringExpressionSimple = self.visitString_expression_simple(
1✔
1389
            ctx.string_expression_simple()
1390
        )
1391
        return AssignTemplateBindingStringExpressionSimple(
1✔
1392
            identifier=identifier, string_expression_simple=string_expression_simple
1393
        )
1394

1395
    def visitAssign_decl_binding(
1✔
1396
        self, ctx: ASLParser.Assign_decl_bindingContext
1397
    ) -> AssignDeclBinding:
1398
        binding: AssignTemplateBinding = self.visit(ctx.assign_template_binding())
1✔
1399
        return AssignDeclBinding(binding=binding)
1✔
1400

1401
    def visitAssign_decl_body(
1✔
1402
        self, ctx: ASLParser.Assign_decl_bodyContext
1403
    ) -> list[AssignDeclBinding]:
1404
        bindings: list[AssignDeclBinding] = []
1✔
1405
        for child in ctx.children:
1✔
1406
            cmp: Component | None = self.visit(child)
1✔
1407
            if isinstance(cmp, AssignDeclBinding):
1✔
1408
                bindings.append(cmp)
1✔
1409
        return bindings
1✔
1410

1411
    def visitAssign_decl(self, ctx: ASLParser.Assign_declContext) -> AssignDecl:
1✔
1412
        declaration_bindings: list[AssignDeclBinding] = self.visit(ctx.assign_decl_body())
1✔
1413
        return AssignDecl(declaration_bindings=declaration_bindings)
1✔
1414

1415
    def visitJsonata_template_value_terminal_float(
1✔
1416
        self, ctx: ASLParser.Jsonata_template_value_terminal_floatContext
1417
    ) -> JSONataTemplateValueTerminalLit:
1418
        float_value = float(ctx.NUMBER().getText())
1✔
1419
        return JSONataTemplateValueTerminalLit(value=float_value)
1✔
1420

1421
    def visitJsonata_template_value_terminal_int(
1✔
1422
        self, ctx: ASLParser.Jsonata_template_value_terminal_intContext
1423
    ) -> JSONataTemplateValueTerminalLit:
1424
        int_value = int(ctx.INT().getText())
1✔
1425
        return JSONataTemplateValueTerminalLit(value=int_value)
1✔
1426

1427
    def visitJsonata_template_value_terminal_bool(
1✔
1428
        self, ctx: ASLParser.Jsonata_template_value_terminal_boolContext
1429
    ) -> JSONataTemplateValueTerminalLit:
1430
        bool_term_rule: int = ctx.children[0].getSymbol().type
1✔
1431
        bool_value: bool = bool_term_rule == ASLLexer.TRUE
1✔
1432
        return JSONataTemplateValueTerminalLit(value=bool_value)
1✔
1433

1434
    def visitJsonata_template_value_terminal_null(
1✔
1435
        self, ctx: ASLParser.Jsonata_template_value_terminal_nullContext
1436
    ) -> JSONataTemplateValueTerminalLit:
1437
        return JSONataTemplateValueTerminalLit(value=None)
1✔
1438

1439
    def visitJsonata_template_value_terminal_string_jsonata(
1✔
1440
        self, ctx: ASLParser.Jsonata_template_value_terminal_string_jsonataContext
1441
    ) -> JSONataTemplateValueTerminalStringJSONata:
1442
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
1443
        return JSONataTemplateValueTerminalStringJSONata(string_jsonata=string_jsonata)
1✔
1444

1445
    def visitJsonata_template_value_terminal_string_literal(
1✔
1446
        self, ctx: ASLParser.Jsonata_template_value_terminal_string_literalContext
1447
    ) -> JSONataTemplateValueTerminalLit:
1448
        string = from_string_literal(ctx.string_literal())
1✔
1449
        return JSONataTemplateValueTerminalLit(value=string)
1✔
1450

1451
    def visitJsonata_template_value(
1✔
1452
        self, ctx: ASLParser.Jsonata_template_valueContext
1453
    ) -> JSONataTemplateValue:
1454
        return self.visit(ctx.children[0])
1✔
1455

1456
    def visitJsonata_template_value_array(
1✔
1457
        self, ctx: ASLParser.Jsonata_template_value_arrayContext
1458
    ) -> JSONataTemplateValueArray:
1459
        values: list[JSONataTemplateValue] = []
1✔
1460
        for child in ctx.children:
1✔
1461
            cmp: Component | None = self.visit(child)
1✔
1462
            if isinstance(cmp, JSONataTemplateValue):
1✔
1463
                values.append(cmp)
1✔
1464
        return JSONataTemplateValueArray(values=values)
1✔
1465

1466
    def visitJsonata_template_value_object(
1✔
1467
        self, ctx: ASLParser.Jsonata_template_value_objectContext
1468
    ) -> JSONataTemplateValueObject:
1469
        bindings: list[JSONataTemplateBinding] = []
1✔
1470
        for child in ctx.children:
1✔
1471
            cmp: Component | None = self.visit(child)
1✔
1472
            if isinstance(cmp, JSONataTemplateBinding):
1✔
1473
                bindings.append(cmp)
1✔
1474
        return JSONataTemplateValueObject(bindings=bindings)
1✔
1475

1476
    def visitJsonata_template_binding(
1✔
1477
        self, ctx: ASLParser.Jsonata_template_bindingContext
1478
    ) -> JSONataTemplateBinding:
1479
        identifier: str = self._inner_string_of(ctx.string_literal())
1✔
1480
        value: JSONataTemplateValue = self.visit(ctx.jsonata_template_value())
1✔
1481
        return JSONataTemplateBinding(identifier=identifier, value=value)
1✔
1482

1483
    def visitArguments_string_jsonata(
1✔
1484
        self, ctx: ASLParser.Arguments_string_jsonataContext
1485
    ) -> ArgumentsStringJSONata:
UNCOV
1486
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
×
UNCOV
1487
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
×
UNCOV
1488
        return ArgumentsStringJSONata(string_jsonata=string_jsonata)
×
1489

1490
    def visitArguments_jsonata_template_value_object(
1✔
1491
        self, ctx: ASLParser.Arguments_jsonata_template_value_objectContext
1492
    ) -> ArgumentsJSONataTemplateValueObject:
1493
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
1494
        jsonata_template_value_object: JSONataTemplateValueObject = self.visit(
1✔
1495
            ctx.jsonata_template_value_object()
1496
        )
1497
        return ArgumentsJSONataTemplateValueObject(
1✔
1498
            jsonata_template_value_object=jsonata_template_value_object
1499
        )
1500

1501
    def visitOutput_decl(self, ctx: ASLParser.Output_declContext) -> Output:
1✔
1502
        jsonata_template_value: JSONataTemplateValue = self.visit(ctx.jsonata_template_value())
1✔
1503
        return Output(jsonata_template_value=jsonata_template_value)
1✔
1504

1505
    def visitItems_array(self, ctx: ASLParser.Items_arrayContext) -> ItemsArray:
1✔
1506
        jsonata_template_value_array: JSONataTemplateValueArray = self.visit(
1✔
1507
            ctx.jsonata_template_value_array()
1508
        )
1509
        return ItemsArray(jsonata_template_value_array=jsonata_template_value_array)
1✔
1510

1511
    def visitItems_jsonata(self, ctx: ASLParser.Items_jsonataContext) -> ItemsJSONata:
1✔
1512
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
1513
        return ItemsJSONata(string_jsonata=string_jsonata)
1✔
1514

1515
    def visitString_sampler(self, ctx: ASLParser.String_samplerContext) -> StringSampler:
1✔
1516
        return self.visit(ctx.children[0])
1✔
1517

1518
    def visitString_literal(self, ctx: ASLParser.String_literalContext) -> StringLiteral:
1✔
1519
        string_literal = from_string_literal(parser_rule_context=ctx)
1✔
1520
        return StringLiteral(literal_value=string_literal)
1✔
1521

1522
    def visitString_jsonpath(self, ctx: ASLParser.String_jsonpathContext) -> StringJsonPath:
1✔
1523
        json_path: str = self._inner_string_of(parser_rule_context=ctx)
1✔
1524
        return StringJsonPath(json_path=json_path)
1✔
1525

1526
    def visitString_context_path(
1✔
1527
        self, ctx: ASLParser.String_context_pathContext
1528
    ) -> StringContextPath:
1529
        context_object_path: str = self._inner_string_of(parser_rule_context=ctx)
1✔
1530
        return StringContextPath(context_object_path=context_object_path)
1✔
1531

1532
    def visitString_variable_sample(
1✔
1533
        self, ctx: ASLParser.String_variable_sampleContext
1534
    ) -> StringVariableSample:
1535
        query_language_mode: QueryLanguageMode = (
1✔
1536
            self._get_current_query_language().query_language_mode
1537
        )
1538
        expression: str = self._inner_string_of(parser_rule_context=ctx)
1✔
1539
        return StringVariableSample(query_language_mode=query_language_mode, expression=expression)
1✔
1540

1541
    def visitString_jsonata(self, ctx: ASLParser.String_jsonataContext) -> StringJSONata:
1✔
1542
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
1543
        expression = self._inner_jsonata_expr(ctx=ctx)
1✔
1544
        return StringJSONata(expression=expression)
1✔
1545

1546
    def visitString_intrinsic_function(
1✔
1547
        self, ctx: ASLParser.String_intrinsic_functionContext
1548
    ) -> StringIntrinsicFunction:
1549
        intrinsic_function_derivation = ctx.STRINGINTRINSICFUNC().getText()[1:-1]
1✔
1550
        function, _ = IntrinsicParser.parse(intrinsic_function_derivation)
1✔
1551
        return StringIntrinsicFunction(
1✔
1552
            intrinsic_function_derivation=intrinsic_function_derivation,
1553
            function=function,
1554
        )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc