herb 0.9.4-arm-linux-gnu → 0.9.6-arm-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/config.yml +57 -21
  3. data/ext/herb/extension.c +8 -0
  4. data/ext/herb/extension_helpers.c +1 -0
  5. data/ext/herb/nodes.c +93 -55
  6. data/lib/herb/3.0/herb.so +0 -0
  7. data/lib/herb/3.1/herb.so +0 -0
  8. data/lib/herb/3.2/herb.so +0 -0
  9. data/lib/herb/3.3/herb.so +0 -0
  10. data/lib/herb/3.4/herb.so +0 -0
  11. data/lib/herb/4.0/herb.so +0 -0
  12. data/lib/herb/action_view/helper_registry.rb +8107 -0
  13. data/lib/herb/ast/nodes.rb +212 -78
  14. data/lib/herb/engine/compiler.rb +4 -6
  15. data/lib/herb/parser_options.rb +7 -2
  16. data/lib/herb/project.rb +2 -5
  17. data/lib/herb/version.rb +1 -1
  18. data/lib/herb/visitor.rb +8 -2
  19. data/sig/herb/action_view/helper_registry.rbs +1144 -0
  20. data/sig/herb/ast/nodes.rbs +85 -34
  21. data/sig/herb/parser_options.rbs +6 -2
  22. data/sig/herb/visitor.rbs +5 -2
  23. data/sig/serialized_ast_nodes.rbs +20 -9
  24. data/src/analyze/action_view/generated_handlers.c +355 -0
  25. data/src/analyze/action_view/generated_handlers.h +16 -0
  26. data/src/analyze/action_view/helper_registry.c +7244 -0
  27. data/src/analyze/action_view/image_tag.c +4 -31
  28. data/src/analyze/action_view/javascript_include_tag.c +1 -42
  29. data/src/analyze/action_view/javascript_tag.c +26 -40
  30. data/src/analyze/action_view/registry.c +2 -2
  31. data/src/analyze/action_view/tag_helper_node_builders.c +23 -2
  32. data/src/analyze/action_view/tag_helpers.c +61 -134
  33. data/src/analyze/action_view/turbo_frame_tag.c +1 -36
  34. data/src/analyze/analyze.c +28 -0
  35. data/src/analyze/analyze_helpers.c +406 -0
  36. data/src/analyze/builders.c +1 -0
  37. data/src/analyze/missing_end.c +16 -0
  38. data/src/analyze/parse_errors.c +3 -2
  39. data/src/analyze/postfix_conditionals.c +326 -0
  40. data/src/analyze/render_nodes.c +231 -35
  41. data/src/analyze/strict_locals.c +22 -338
  42. data/src/analyze/ternary_conditionals.c +265 -0
  43. data/src/analyze/transform.c +23 -2
  44. data/src/ast/ast_nodes.c +114 -57
  45. data/src/ast/ast_pretty_print.c +109 -25
  46. data/src/include/analyze/action_view/helper_registry.h +325 -0
  47. data/src/include/analyze/action_view/tag_helper_handler.h +3 -0
  48. data/src/include/analyze/action_view/tag_helper_node_builders.h +7 -0
  49. data/src/include/analyze/action_view/tag_helpers.h +0 -1
  50. data/src/include/analyze/helpers.h +18 -0
  51. data/src/include/analyze/postfix_conditionals.h +9 -0
  52. data/src/include/analyze/ternary_conditionals.h +15 -0
  53. data/src/include/ast/ast_nodes.h +27 -13
  54. data/src/include/parser/parser.h +1 -0
  55. data/src/include/version.h +1 -1
  56. data/src/parser/match_tags.c +37 -6
  57. data/src/parser.c +9 -0
  58. data/src/visitor.c +50 -7
  59. data/templates/java/org/herb/ast/HelperRegistry.java.erb +258 -0
  60. data/templates/javascript/packages/core/src/action-view-helpers.ts.erb +171 -0
  61. data/templates/javascript/packages/core/src/nodes.ts.erb +5 -1
  62. data/templates/lib/herb/action_view/helper_registry.rb.erb +288 -0
  63. data/templates/rust/src/action_view_helpers.rs.erb +154 -0
  64. data/templates/src/analyze/action_view/generated_handlers.c.erb +230 -0
  65. data/templates/src/analyze/action_view/generated_handlers.h.erb +12 -0
  66. data/templates/src/analyze/action_view/helper_registry.c.erb +114 -0
  67. data/templates/src/include/analyze/action_view/helper_registry.h.erb +82 -0
  68. data/templates/template.rb +338 -1
  69. metadata +19 -3
  70. data/src/analyze/action_view/content_tag.c +0 -78
  71. data/src/analyze/action_view/tag.c +0 -87
@@ -113,6 +113,13 @@ bool transform_erb_nodes(const AST_NODE_T* node, void* data) {
113
113
  hb_array_free(&old_array);
114
114
  }
115
115
 
116
+ if (node->type == AST_ERB_BLOCK_NODE) {
117
+ AST_ERB_BLOCK_NODE_T* erb_block_node = (AST_ERB_BLOCK_NODE_T*) node;
118
+ hb_array_T* old_array = erb_block_node->block_arguments;
119
+ erb_block_node->block_arguments = rewrite_node_array((AST_NODE_T*) node, erb_block_node->block_arguments, context);
120
+ hb_array_free(&old_array);
121
+ }
122
+
116
123
  if (node->type == AST_ERB_WHEN_NODE) {
117
124
  AST_ERB_WHEN_NODE_T* erb_when_node = (AST_ERB_WHEN_NODE_T*) node;
118
125
  hb_array_T* old_array = erb_when_node->statements;
@@ -197,10 +204,24 @@ bool transform_erb_nodes(const AST_NODE_T* node, void* data) {
197
204
  hb_array_free(&old_array);
198
205
  }
199
206
 
207
+ if (node->type == AST_RUBY_RENDER_KEYWORDS_NODE) {
208
+ AST_RUBY_RENDER_KEYWORDS_NODE_T* ruby_render_keywords_node = (AST_RUBY_RENDER_KEYWORDS_NODE_T*) node;
209
+ hb_array_T* old_array = ruby_render_keywords_node->locals;
210
+ ruby_render_keywords_node->locals = rewrite_node_array((AST_NODE_T*) node, ruby_render_keywords_node->locals, context);
211
+ hb_array_free(&old_array);
212
+ }
213
+
214
+ if (node->type == AST_ERB_RENDER_NODE) {
215
+ AST_ERB_RENDER_NODE_T* erb_render_node = (AST_ERB_RENDER_NODE_T*) node;
216
+ hb_array_T* old_array = erb_render_node->body;
217
+ erb_render_node->body = rewrite_node_array((AST_NODE_T*) node, erb_render_node->body, context);
218
+ hb_array_free(&old_array);
219
+ }
220
+
200
221
  if (node->type == AST_ERB_RENDER_NODE) {
201
222
  AST_ERB_RENDER_NODE_T* erb_render_node = (AST_ERB_RENDER_NODE_T*) node;
202
- hb_array_T* old_array = erb_render_node->locals;
203
- erb_render_node->locals = rewrite_node_array((AST_NODE_T*) node, erb_render_node->locals, context);
223
+ hb_array_T* old_array = erb_render_node->block_arguments;
224
+ erb_render_node->block_arguments = rewrite_node_array((AST_NODE_T*) node, erb_render_node->block_arguments, context);
204
225
  hb_array_free(&old_array);
205
226
  }
206
227
 
data/src/ast/ast_nodes.c CHANGED
@@ -376,7 +376,7 @@ AST_ERB_IF_NODE_T* ast_erb_if_node_init(token_T* tag_opening, token_T* content,
376
376
  return erb_if_node;
377
377
  }
378
378
 
379
- AST_ERB_BLOCK_NODE_T* ast_erb_block_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, herb_prism_node_T prism_node, hb_array_T* body, struct AST_ERB_RESCUE_NODE_STRUCT* rescue_clause, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_ENSURE_NODE_STRUCT* ensure_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors, hb_allocator_T* allocator) {
379
+ AST_ERB_BLOCK_NODE_T* ast_erb_block_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, herb_prism_node_T prism_node, hb_array_T* body, hb_array_T* block_arguments, struct AST_ERB_RESCUE_NODE_STRUCT* rescue_clause, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_ENSURE_NODE_STRUCT* ensure_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors, hb_allocator_T* allocator) {
380
380
  AST_ERB_BLOCK_NODE_T* erb_block_node = hb_allocator_alloc(allocator, sizeof(AST_ERB_BLOCK_NODE_T));
381
381
 
382
382
  if (!erb_block_node) { return NULL; }
@@ -388,6 +388,7 @@ AST_ERB_BLOCK_NODE_T* ast_erb_block_node_init(token_T* tag_opening, token_T* con
388
388
  erb_block_node->tag_closing = token_copy(tag_closing, allocator);
389
389
  erb_block_node->prism_node = prism_node;
390
390
  erb_block_node->body = body;
391
+ erb_block_node->block_arguments = block_arguments;
391
392
  erb_block_node->rescue_clause = rescue_clause;
392
393
  erb_block_node->else_clause = else_clause;
393
394
  erb_block_node->ensure_clause = ensure_clause;
@@ -584,7 +585,36 @@ AST_RUBY_RENDER_LOCAL_NODE_T* ast_ruby_render_local_node_init(token_T* name, str
584
585
  return ruby_render_local_node;
585
586
  }
586
587
 
587
- AST_ERB_RENDER_NODE_T* ast_erb_render_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, analyzed_ruby_T* analyzed_ruby, herb_prism_node_T prism_node, token_T* partial, token_T* template_path, token_T* layout, token_T* file, token_T* inline_template, token_T* body, token_T* plain, token_T* html, token_T* renderable, token_T* collection, token_T* object, token_T* as_name, token_T* spacer_template, token_T* formats, token_T* variants, token_T* handlers, token_T* content_type, hb_array_T* locals, position_T start_position, position_T end_position, hb_array_T* errors, hb_allocator_T* allocator) {
588
+ AST_RUBY_RENDER_KEYWORDS_NODE_T* ast_ruby_render_keywords_node_init(token_T* partial, token_T* template_path, token_T* layout, token_T* file, token_T* inline_template, token_T* body, token_T* plain, token_T* html, token_T* renderable, token_T* collection, token_T* object, token_T* as_name, token_T* spacer_template, token_T* formats, token_T* variants, token_T* handlers, token_T* content_type, hb_array_T* locals, position_T start_position, position_T end_position, hb_array_T* errors, hb_allocator_T* allocator) {
589
+ AST_RUBY_RENDER_KEYWORDS_NODE_T* ruby_render_keywords_node = hb_allocator_alloc(allocator, sizeof(AST_RUBY_RENDER_KEYWORDS_NODE_T));
590
+
591
+ if (!ruby_render_keywords_node) { return NULL; }
592
+
593
+ ast_node_init(&ruby_render_keywords_node->base, AST_RUBY_RENDER_KEYWORDS_NODE, start_position, end_position, errors, allocator);
594
+
595
+ ruby_render_keywords_node->partial = token_copy(partial, allocator);
596
+ ruby_render_keywords_node->template_path = token_copy(template_path, allocator);
597
+ ruby_render_keywords_node->layout = token_copy(layout, allocator);
598
+ ruby_render_keywords_node->file = token_copy(file, allocator);
599
+ ruby_render_keywords_node->inline_template = token_copy(inline_template, allocator);
600
+ ruby_render_keywords_node->body = token_copy(body, allocator);
601
+ ruby_render_keywords_node->plain = token_copy(plain, allocator);
602
+ ruby_render_keywords_node->html = token_copy(html, allocator);
603
+ ruby_render_keywords_node->renderable = token_copy(renderable, allocator);
604
+ ruby_render_keywords_node->collection = token_copy(collection, allocator);
605
+ ruby_render_keywords_node->object = token_copy(object, allocator);
606
+ ruby_render_keywords_node->as_name = token_copy(as_name, allocator);
607
+ ruby_render_keywords_node->spacer_template = token_copy(spacer_template, allocator);
608
+ ruby_render_keywords_node->formats = token_copy(formats, allocator);
609
+ ruby_render_keywords_node->variants = token_copy(variants, allocator);
610
+ ruby_render_keywords_node->handlers = token_copy(handlers, allocator);
611
+ ruby_render_keywords_node->content_type = token_copy(content_type, allocator);
612
+ ruby_render_keywords_node->locals = locals;
613
+
614
+ return ruby_render_keywords_node;
615
+ }
616
+
617
+ AST_ERB_RENDER_NODE_T* ast_erb_render_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, analyzed_ruby_T* analyzed_ruby, herb_prism_node_T prism_node, struct AST_RUBY_RENDER_KEYWORDS_NODE_STRUCT* keywords, hb_array_T* body, hb_array_T* block_arguments, struct AST_ERB_RESCUE_NODE_STRUCT* rescue_clause, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_ENSURE_NODE_STRUCT* ensure_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors, hb_allocator_T* allocator) {
588
618
  AST_ERB_RENDER_NODE_T* erb_render_node = hb_allocator_alloc(allocator, sizeof(AST_ERB_RENDER_NODE_T));
589
619
 
590
620
  if (!erb_render_node) { return NULL; }
@@ -596,41 +626,30 @@ AST_ERB_RENDER_NODE_T* ast_erb_render_node_init(token_T* tag_opening, token_T* c
596
626
  erb_render_node->tag_closing = token_copy(tag_closing, allocator);
597
627
  erb_render_node->analyzed_ruby = analyzed_ruby;
598
628
  erb_render_node->prism_node = prism_node;
599
- erb_render_node->partial = token_copy(partial, allocator);
600
- erb_render_node->template_path = token_copy(template_path, allocator);
601
- erb_render_node->layout = token_copy(layout, allocator);
602
- erb_render_node->file = token_copy(file, allocator);
603
- erb_render_node->inline_template = token_copy(inline_template, allocator);
604
- erb_render_node->body = token_copy(body, allocator);
605
- erb_render_node->plain = token_copy(plain, allocator);
606
- erb_render_node->html = token_copy(html, allocator);
607
- erb_render_node->renderable = token_copy(renderable, allocator);
608
- erb_render_node->collection = token_copy(collection, allocator);
609
- erb_render_node->object = token_copy(object, allocator);
610
- erb_render_node->as_name = token_copy(as_name, allocator);
611
- erb_render_node->spacer_template = token_copy(spacer_template, allocator);
612
- erb_render_node->formats = token_copy(formats, allocator);
613
- erb_render_node->variants = token_copy(variants, allocator);
614
- erb_render_node->handlers = token_copy(handlers, allocator);
615
- erb_render_node->content_type = token_copy(content_type, allocator);
616
- erb_render_node->locals = locals;
629
+ erb_render_node->keywords = keywords;
630
+ erb_render_node->body = body;
631
+ erb_render_node->block_arguments = block_arguments;
632
+ erb_render_node->rescue_clause = rescue_clause;
633
+ erb_render_node->else_clause = else_clause;
634
+ erb_render_node->ensure_clause = ensure_clause;
635
+ erb_render_node->end_node = end_node;
617
636
 
618
637
  return erb_render_node;
619
638
  }
620
639
 
621
- AST_RUBY_STRICT_LOCAL_NODE_T* ast_ruby_strict_local_node_init(token_T* name, struct AST_RUBY_LITERAL_NODE_STRUCT* default_value, bool required, bool double_splat, position_T start_position, position_T end_position, hb_array_T* errors, hb_allocator_T* allocator) {
622
- AST_RUBY_STRICT_LOCAL_NODE_T* ruby_strict_local_node = hb_allocator_alloc(allocator, sizeof(AST_RUBY_STRICT_LOCAL_NODE_T));
640
+ AST_RUBY_PARAMETER_NODE_T* ast_ruby_parameter_node_init(token_T* name, struct AST_RUBY_LITERAL_NODE_STRUCT* default_value, hb_string_T kind, bool required, position_T start_position, position_T end_position, hb_array_T* errors, hb_allocator_T* allocator) {
641
+ AST_RUBY_PARAMETER_NODE_T* ruby_parameter_node = hb_allocator_alloc(allocator, sizeof(AST_RUBY_PARAMETER_NODE_T));
623
642
 
624
- if (!ruby_strict_local_node) { return NULL; }
643
+ if (!ruby_parameter_node) { return NULL; }
625
644
 
626
- ast_node_init(&ruby_strict_local_node->base, AST_RUBY_STRICT_LOCAL_NODE, start_position, end_position, errors, allocator);
645
+ ast_node_init(&ruby_parameter_node->base, AST_RUBY_PARAMETER_NODE, start_position, end_position, errors, allocator);
627
646
 
628
- ruby_strict_local_node->name = token_copy(name, allocator);
629
- ruby_strict_local_node->default_value = default_value;
630
- ruby_strict_local_node->required = required;
631
- ruby_strict_local_node->double_splat = double_splat;
647
+ ruby_parameter_node->name = token_copy(name, allocator);
648
+ ruby_parameter_node->default_value = default_value;
649
+ ruby_parameter_node->kind = hb_string_copy(kind, allocator);
650
+ ruby_parameter_node->required = required;
632
651
 
633
- return ruby_strict_local_node;
652
+ return ruby_parameter_node;
634
653
  }
635
654
 
636
655
  AST_ERB_STRICT_LOCALS_NODE_T* ast_erb_strict_locals_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, analyzed_ruby_T* analyzed_ruby, herb_prism_node_T prism_node, hb_array_T* locals, position_T start_position, position_T end_position, hb_array_T* errors, hb_allocator_T* allocator) {
@@ -719,8 +738,9 @@ hb_string_T ast_node_type_to_string(AST_NODE_T* node) {
719
738
  case AST_ERB_BEGIN_NODE: return hb_string("AST_ERB_BEGIN_NODE");
720
739
  case AST_ERB_UNLESS_NODE: return hb_string("AST_ERB_UNLESS_NODE");
721
740
  case AST_RUBY_RENDER_LOCAL_NODE: return hb_string("AST_RUBY_RENDER_LOCAL_NODE");
741
+ case AST_RUBY_RENDER_KEYWORDS_NODE: return hb_string("AST_RUBY_RENDER_KEYWORDS_NODE");
722
742
  case AST_ERB_RENDER_NODE: return hb_string("AST_ERB_RENDER_NODE");
723
- case AST_RUBY_STRICT_LOCAL_NODE: return hb_string("AST_RUBY_STRICT_LOCAL_NODE");
743
+ case AST_RUBY_PARAMETER_NODE: return hb_string("AST_RUBY_PARAMETER_NODE");
724
744
  case AST_ERB_STRICT_LOCALS_NODE: return hb_string("AST_ERB_STRICT_LOCALS_NODE");
725
745
  case AST_ERB_YIELD_NODE: return hb_string("AST_ERB_YIELD_NODE");
726
746
  case AST_ERB_IN_NODE: return hb_string("AST_ERB_IN_NODE");
@@ -768,8 +788,9 @@ hb_string_T ast_node_human_type(AST_NODE_T* node) {
768
788
  case AST_ERB_BEGIN_NODE: return hb_string("ERBBeginNode");
769
789
  case AST_ERB_UNLESS_NODE: return hb_string("ERBUnlessNode");
770
790
  case AST_RUBY_RENDER_LOCAL_NODE: return hb_string("RubyRenderLocalNode");
791
+ case AST_RUBY_RENDER_KEYWORDS_NODE: return hb_string("RubyRenderKeywordsNode");
771
792
  case AST_ERB_RENDER_NODE: return hb_string("ERBRenderNode");
772
- case AST_RUBY_STRICT_LOCAL_NODE: return hb_string("RubyStrictLocalNode");
793
+ case AST_RUBY_PARAMETER_NODE: return hb_string("RubyParameterNode");
773
794
  case AST_ERB_STRICT_LOCALS_NODE: return hb_string("ERBStrictLocalsNode");
774
795
  case AST_ERB_YIELD_NODE: return hb_string("ERBYieldNode");
775
796
  case AST_ERB_IN_NODE: return hb_string("ERBInNode");
@@ -1108,6 +1129,14 @@ static void ast_free_erb_block_node(AST_ERB_BLOCK_NODE_T* erb_block_node, hb_all
1108
1129
 
1109
1130
  hb_array_free(&erb_block_node->body);
1110
1131
  }
1132
+ if (erb_block_node->block_arguments != NULL) {
1133
+ for (size_t i = 0; i < hb_array_size(erb_block_node->block_arguments); i++) {
1134
+ AST_NODE_T* child = hb_array_get(erb_block_node->block_arguments, i);
1135
+ if (child) { ast_node_free(child, allocator); }
1136
+ }
1137
+
1138
+ hb_array_free(&erb_block_node->block_arguments);
1139
+ }
1111
1140
  ast_node_free((AST_NODE_T*) erb_block_node->rescue_clause, allocator);
1112
1141
  ast_node_free((AST_NODE_T*) erb_block_node->else_clause, allocator);
1113
1142
  ast_node_free((AST_NODE_T*) erb_block_node->ensure_clause, allocator);
@@ -1322,6 +1351,36 @@ static void ast_free_ruby_render_local_node(AST_RUBY_RENDER_LOCAL_NODE_T* ruby_r
1322
1351
  ast_free_base_node(&ruby_render_local_node->base, allocator);
1323
1352
  }
1324
1353
 
1354
+ static void ast_free_ruby_render_keywords_node(AST_RUBY_RENDER_KEYWORDS_NODE_T* ruby_render_keywords_node, hb_allocator_T* allocator) {
1355
+ if (ruby_render_keywords_node->partial != NULL) { token_free(ruby_render_keywords_node->partial, allocator); }
1356
+ if (ruby_render_keywords_node->template_path != NULL) { token_free(ruby_render_keywords_node->template_path, allocator); }
1357
+ if (ruby_render_keywords_node->layout != NULL) { token_free(ruby_render_keywords_node->layout, allocator); }
1358
+ if (ruby_render_keywords_node->file != NULL) { token_free(ruby_render_keywords_node->file, allocator); }
1359
+ if (ruby_render_keywords_node->inline_template != NULL) { token_free(ruby_render_keywords_node->inline_template, allocator); }
1360
+ if (ruby_render_keywords_node->body != NULL) { token_free(ruby_render_keywords_node->body, allocator); }
1361
+ if (ruby_render_keywords_node->plain != NULL) { token_free(ruby_render_keywords_node->plain, allocator); }
1362
+ if (ruby_render_keywords_node->html != NULL) { token_free(ruby_render_keywords_node->html, allocator); }
1363
+ if (ruby_render_keywords_node->renderable != NULL) { token_free(ruby_render_keywords_node->renderable, allocator); }
1364
+ if (ruby_render_keywords_node->collection != NULL) { token_free(ruby_render_keywords_node->collection, allocator); }
1365
+ if (ruby_render_keywords_node->object != NULL) { token_free(ruby_render_keywords_node->object, allocator); }
1366
+ if (ruby_render_keywords_node->as_name != NULL) { token_free(ruby_render_keywords_node->as_name, allocator); }
1367
+ if (ruby_render_keywords_node->spacer_template != NULL) { token_free(ruby_render_keywords_node->spacer_template, allocator); }
1368
+ if (ruby_render_keywords_node->formats != NULL) { token_free(ruby_render_keywords_node->formats, allocator); }
1369
+ if (ruby_render_keywords_node->variants != NULL) { token_free(ruby_render_keywords_node->variants, allocator); }
1370
+ if (ruby_render_keywords_node->handlers != NULL) { token_free(ruby_render_keywords_node->handlers, allocator); }
1371
+ if (ruby_render_keywords_node->content_type != NULL) { token_free(ruby_render_keywords_node->content_type, allocator); }
1372
+ if (ruby_render_keywords_node->locals != NULL) {
1373
+ for (size_t i = 0; i < hb_array_size(ruby_render_keywords_node->locals); i++) {
1374
+ AST_NODE_T* child = hb_array_get(ruby_render_keywords_node->locals, i);
1375
+ if (child) { ast_node_free(child, allocator); }
1376
+ }
1377
+
1378
+ hb_array_free(&ruby_render_keywords_node->locals);
1379
+ }
1380
+
1381
+ ast_free_base_node(&ruby_render_keywords_node->base, allocator);
1382
+ }
1383
+
1325
1384
  static void ast_free_erb_render_node(AST_ERB_RENDER_NODE_T* erb_render_node, hb_allocator_T* allocator) {
1326
1385
  if (erb_render_node->tag_opening != NULL) { token_free(erb_render_node->tag_opening, allocator); }
1327
1386
  if (erb_render_node->content != NULL) { token_free(erb_render_node->content, allocator); }
@@ -1330,40 +1389,37 @@ static void ast_free_erb_render_node(AST_ERB_RENDER_NODE_T* erb_render_node, hb_
1330
1389
  free_analyzed_ruby(erb_render_node->analyzed_ruby);
1331
1390
  }
1332
1391
  /* prism_node is a borrowed reference into the prism context, not freed here */
1333
- if (erb_render_node->partial != NULL) { token_free(erb_render_node->partial, allocator); }
1334
- if (erb_render_node->template_path != NULL) { token_free(erb_render_node->template_path, allocator); }
1335
- if (erb_render_node->layout != NULL) { token_free(erb_render_node->layout, allocator); }
1336
- if (erb_render_node->file != NULL) { token_free(erb_render_node->file, allocator); }
1337
- if (erb_render_node->inline_template != NULL) { token_free(erb_render_node->inline_template, allocator); }
1338
- if (erb_render_node->body != NULL) { token_free(erb_render_node->body, allocator); }
1339
- if (erb_render_node->plain != NULL) { token_free(erb_render_node->plain, allocator); }
1340
- if (erb_render_node->html != NULL) { token_free(erb_render_node->html, allocator); }
1341
- if (erb_render_node->renderable != NULL) { token_free(erb_render_node->renderable, allocator); }
1342
- if (erb_render_node->collection != NULL) { token_free(erb_render_node->collection, allocator); }
1343
- if (erb_render_node->object != NULL) { token_free(erb_render_node->object, allocator); }
1344
- if (erb_render_node->as_name != NULL) { token_free(erb_render_node->as_name, allocator); }
1345
- if (erb_render_node->spacer_template != NULL) { token_free(erb_render_node->spacer_template, allocator); }
1346
- if (erb_render_node->formats != NULL) { token_free(erb_render_node->formats, allocator); }
1347
- if (erb_render_node->variants != NULL) { token_free(erb_render_node->variants, allocator); }
1348
- if (erb_render_node->handlers != NULL) { token_free(erb_render_node->handlers, allocator); }
1349
- if (erb_render_node->content_type != NULL) { token_free(erb_render_node->content_type, allocator); }
1350
- if (erb_render_node->locals != NULL) {
1351
- for (size_t i = 0; i < hb_array_size(erb_render_node->locals); i++) {
1352
- AST_NODE_T* child = hb_array_get(erb_render_node->locals, i);
1392
+ ast_node_free((AST_NODE_T*) erb_render_node->keywords, allocator);
1393
+ if (erb_render_node->body != NULL) {
1394
+ for (size_t i = 0; i < hb_array_size(erb_render_node->body); i++) {
1395
+ AST_NODE_T* child = hb_array_get(erb_render_node->body, i);
1396
+ if (child) { ast_node_free(child, allocator); }
1397
+ }
1398
+
1399
+ hb_array_free(&erb_render_node->body);
1400
+ }
1401
+ if (erb_render_node->block_arguments != NULL) {
1402
+ for (size_t i = 0; i < hb_array_size(erb_render_node->block_arguments); i++) {
1403
+ AST_NODE_T* child = hb_array_get(erb_render_node->block_arguments, i);
1353
1404
  if (child) { ast_node_free(child, allocator); }
1354
1405
  }
1355
1406
 
1356
- hb_array_free(&erb_render_node->locals);
1407
+ hb_array_free(&erb_render_node->block_arguments);
1357
1408
  }
1409
+ ast_node_free((AST_NODE_T*) erb_render_node->rescue_clause, allocator);
1410
+ ast_node_free((AST_NODE_T*) erb_render_node->else_clause, allocator);
1411
+ ast_node_free((AST_NODE_T*) erb_render_node->ensure_clause, allocator);
1412
+ ast_node_free((AST_NODE_T*) erb_render_node->end_node, allocator);
1358
1413
 
1359
1414
  ast_free_base_node(&erb_render_node->base, allocator);
1360
1415
  }
1361
1416
 
1362
- static void ast_free_ruby_strict_local_node(AST_RUBY_STRICT_LOCAL_NODE_T* ruby_strict_local_node, hb_allocator_T* allocator) {
1363
- if (ruby_strict_local_node->name != NULL) { token_free(ruby_strict_local_node->name, allocator); }
1364
- ast_node_free((AST_NODE_T*) ruby_strict_local_node->default_value, allocator);
1417
+ static void ast_free_ruby_parameter_node(AST_RUBY_PARAMETER_NODE_T* ruby_parameter_node, hb_allocator_T* allocator) {
1418
+ if (ruby_parameter_node->name != NULL) { token_free(ruby_parameter_node->name, allocator); }
1419
+ ast_node_free((AST_NODE_T*) ruby_parameter_node->default_value, allocator);
1420
+ if (ruby_parameter_node->kind.data != NULL) { hb_allocator_dealloc(allocator, ruby_parameter_node->kind.data); }
1365
1421
 
1366
- ast_free_base_node(&ruby_strict_local_node->base, allocator);
1422
+ ast_free_base_node(&ruby_parameter_node->base, allocator);
1367
1423
  }
1368
1424
 
1369
1425
  static void ast_free_erb_strict_locals_node(AST_ERB_STRICT_LOCALS_NODE_T* erb_strict_locals_node, hb_allocator_T* allocator) {
@@ -1452,8 +1508,9 @@ void ast_node_free(AST_NODE_T* node, hb_allocator_T* allocator) {
1452
1508
  case AST_ERB_BEGIN_NODE: ast_free_erb_begin_node((AST_ERB_BEGIN_NODE_T*) node, allocator); break;
1453
1509
  case AST_ERB_UNLESS_NODE: ast_free_erb_unless_node((AST_ERB_UNLESS_NODE_T*) node, allocator); break;
1454
1510
  case AST_RUBY_RENDER_LOCAL_NODE: ast_free_ruby_render_local_node((AST_RUBY_RENDER_LOCAL_NODE_T*) node, allocator); break;
1511
+ case AST_RUBY_RENDER_KEYWORDS_NODE: ast_free_ruby_render_keywords_node((AST_RUBY_RENDER_KEYWORDS_NODE_T*) node, allocator); break;
1455
1512
  case AST_ERB_RENDER_NODE: ast_free_erb_render_node((AST_ERB_RENDER_NODE_T*) node, allocator); break;
1456
- case AST_RUBY_STRICT_LOCAL_NODE: ast_free_ruby_strict_local_node((AST_RUBY_STRICT_LOCAL_NODE_T*) node, allocator); break;
1513
+ case AST_RUBY_PARAMETER_NODE: ast_free_ruby_parameter_node((AST_RUBY_PARAMETER_NODE_T*) node, allocator); break;
1457
1514
  case AST_ERB_STRICT_LOCALS_NODE: ast_free_erb_strict_locals_node((AST_ERB_STRICT_LOCALS_NODE_T*) node, allocator); break;
1458
1515
  case AST_ERB_YIELD_NODE: ast_free_erb_yield_node((AST_ERB_YIELD_NODE_T*) node, allocator); break;
1459
1516
  case AST_ERB_IN_NODE: ast_free_erb_in_node((AST_ERB_IN_NODE_T*) node, allocator); break;
@@ -473,6 +473,7 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
473
473
  hb_buffer_append(buffer, " (pm_node_t*)\n");
474
474
  }
475
475
  pretty_print_array(hb_string("body"), erb_block_node->body, indent, relative_indent, false, buffer);
476
+ pretty_print_array(hb_string("block_arguments"), erb_block_node->block_arguments, indent, relative_indent, false, buffer);
476
477
 
477
478
  pretty_print_label(hb_string("rescue_clause"), indent, relative_indent, false, buffer);
478
479
 
@@ -923,6 +924,30 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
923
924
 
924
925
  } break;
925
926
 
927
+ case AST_RUBY_RENDER_KEYWORDS_NODE: {
928
+ const AST_RUBY_RENDER_KEYWORDS_NODE_T* ruby_render_keywords_node = (AST_RUBY_RENDER_KEYWORDS_NODE_T*) node;
929
+
930
+ pretty_print_errors(node, indent, relative_indent, false, buffer);
931
+ pretty_print_token_property(ruby_render_keywords_node->partial, hb_string("partial"), indent, relative_indent, false, buffer);
932
+ pretty_print_token_property(ruby_render_keywords_node->template_path, hb_string("template_path"), indent, relative_indent, false, buffer);
933
+ pretty_print_token_property(ruby_render_keywords_node->layout, hb_string("layout"), indent, relative_indent, false, buffer);
934
+ pretty_print_token_property(ruby_render_keywords_node->file, hb_string("file"), indent, relative_indent, false, buffer);
935
+ pretty_print_token_property(ruby_render_keywords_node->inline_template, hb_string("inline_template"), indent, relative_indent, false, buffer);
936
+ pretty_print_token_property(ruby_render_keywords_node->body, hb_string("body"), indent, relative_indent, false, buffer);
937
+ pretty_print_token_property(ruby_render_keywords_node->plain, hb_string("plain"), indent, relative_indent, false, buffer);
938
+ pretty_print_token_property(ruby_render_keywords_node->html, hb_string("html"), indent, relative_indent, false, buffer);
939
+ pretty_print_token_property(ruby_render_keywords_node->renderable, hb_string("renderable"), indent, relative_indent, false, buffer);
940
+ pretty_print_token_property(ruby_render_keywords_node->collection, hb_string("collection"), indent, relative_indent, false, buffer);
941
+ pretty_print_token_property(ruby_render_keywords_node->object, hb_string("object"), indent, relative_indent, false, buffer);
942
+ pretty_print_token_property(ruby_render_keywords_node->as_name, hb_string("as_name"), indent, relative_indent, false, buffer);
943
+ pretty_print_token_property(ruby_render_keywords_node->spacer_template, hb_string("spacer_template"), indent, relative_indent, false, buffer);
944
+ pretty_print_token_property(ruby_render_keywords_node->formats, hb_string("formats"), indent, relative_indent, false, buffer);
945
+ pretty_print_token_property(ruby_render_keywords_node->variants, hb_string("variants"), indent, relative_indent, false, buffer);
946
+ pretty_print_token_property(ruby_render_keywords_node->handlers, hb_string("handlers"), indent, relative_indent, false, buffer);
947
+ pretty_print_token_property(ruby_render_keywords_node->content_type, hb_string("content_type"), indent, relative_indent, false, buffer);
948
+ pretty_print_array(hb_string("locals"), ruby_render_keywords_node->locals, indent, relative_indent, true, buffer);
949
+ } break;
950
+
926
951
  case AST_ERB_RENDER_NODE: {
927
952
  const AST_ERB_RENDER_NODE_T* erb_render_node = (AST_ERB_RENDER_NODE_T*) node;
928
953
 
@@ -955,48 +980,107 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
955
980
  pretty_print_label(hb_string("prism_node"), indent, relative_indent, false, buffer);
956
981
  hb_buffer_append(buffer, " (pm_node_t*)\n");
957
982
  }
958
- pretty_print_token_property(erb_render_node->partial, hb_string("partial"), indent, relative_indent, false, buffer);
959
- pretty_print_token_property(erb_render_node->template_path, hb_string("template_path"), indent, relative_indent, false, buffer);
960
- pretty_print_token_property(erb_render_node->layout, hb_string("layout"), indent, relative_indent, false, buffer);
961
- pretty_print_token_property(erb_render_node->file, hb_string("file"), indent, relative_indent, false, buffer);
962
- pretty_print_token_property(erb_render_node->inline_template, hb_string("inline_template"), indent, relative_indent, false, buffer);
963
- pretty_print_token_property(erb_render_node->body, hb_string("body"), indent, relative_indent, false, buffer);
964
- pretty_print_token_property(erb_render_node->plain, hb_string("plain"), indent, relative_indent, false, buffer);
965
- pretty_print_token_property(erb_render_node->html, hb_string("html"), indent, relative_indent, false, buffer);
966
- pretty_print_token_property(erb_render_node->renderable, hb_string("renderable"), indent, relative_indent, false, buffer);
967
- pretty_print_token_property(erb_render_node->collection, hb_string("collection"), indent, relative_indent, false, buffer);
968
- pretty_print_token_property(erb_render_node->object, hb_string("object"), indent, relative_indent, false, buffer);
969
- pretty_print_token_property(erb_render_node->as_name, hb_string("as_name"), indent, relative_indent, false, buffer);
970
- pretty_print_token_property(erb_render_node->spacer_template, hb_string("spacer_template"), indent, relative_indent, false, buffer);
971
- pretty_print_token_property(erb_render_node->formats, hb_string("formats"), indent, relative_indent, false, buffer);
972
- pretty_print_token_property(erb_render_node->variants, hb_string("variants"), indent, relative_indent, false, buffer);
973
- pretty_print_token_property(erb_render_node->handlers, hb_string("handlers"), indent, relative_indent, false, buffer);
974
- pretty_print_token_property(erb_render_node->content_type, hb_string("content_type"), indent, relative_indent, false, buffer);
975
- pretty_print_array(hb_string("locals"), erb_render_node->locals, indent, relative_indent, true, buffer);
983
+
984
+ pretty_print_label(hb_string("keywords"), indent, relative_indent, false, buffer);
985
+
986
+ if (erb_render_node->keywords) {
987
+ hb_buffer_append(buffer, "\n");
988
+ pretty_print_indent(buffer, indent);
989
+ pretty_print_indent(buffer, relative_indent + 1);
990
+
991
+ hb_buffer_append(buffer, "└── ");
992
+ ast_pretty_print_node((AST_NODE_T*) erb_render_node->keywords, indent, relative_indent + 2, buffer);
993
+ } else {
994
+ hb_buffer_append(buffer, " ∅\n");
995
+ }
996
+ hb_buffer_append(buffer, "\n");
997
+
998
+ pretty_print_array(hb_string("body"), erb_render_node->body, indent, relative_indent, false, buffer);
999
+ pretty_print_array(hb_string("block_arguments"), erb_render_node->block_arguments, indent, relative_indent, false, buffer);
1000
+
1001
+ pretty_print_label(hb_string("rescue_clause"), indent, relative_indent, false, buffer);
1002
+
1003
+ if (erb_render_node->rescue_clause) {
1004
+ hb_buffer_append(buffer, "\n");
1005
+ pretty_print_indent(buffer, indent);
1006
+ pretty_print_indent(buffer, relative_indent + 1);
1007
+
1008
+ hb_buffer_append(buffer, "└── ");
1009
+ ast_pretty_print_node((AST_NODE_T*) erb_render_node->rescue_clause, indent, relative_indent + 2, buffer);
1010
+ } else {
1011
+ hb_buffer_append(buffer, " ∅\n");
1012
+ }
1013
+ hb_buffer_append(buffer, "\n");
1014
+
1015
+
1016
+ pretty_print_label(hb_string("else_clause"), indent, relative_indent, false, buffer);
1017
+
1018
+ if (erb_render_node->else_clause) {
1019
+ hb_buffer_append(buffer, "\n");
1020
+ pretty_print_indent(buffer, indent);
1021
+ pretty_print_indent(buffer, relative_indent + 1);
1022
+
1023
+ hb_buffer_append(buffer, "└── ");
1024
+ ast_pretty_print_node((AST_NODE_T*) erb_render_node->else_clause, indent, relative_indent + 2, buffer);
1025
+ } else {
1026
+ hb_buffer_append(buffer, " ∅\n");
1027
+ }
1028
+ hb_buffer_append(buffer, "\n");
1029
+
1030
+
1031
+ pretty_print_label(hb_string("ensure_clause"), indent, relative_indent, false, buffer);
1032
+
1033
+ if (erb_render_node->ensure_clause) {
1034
+ hb_buffer_append(buffer, "\n");
1035
+ pretty_print_indent(buffer, indent);
1036
+ pretty_print_indent(buffer, relative_indent + 1);
1037
+
1038
+ hb_buffer_append(buffer, "└── ");
1039
+ ast_pretty_print_node((AST_NODE_T*) erb_render_node->ensure_clause, indent, relative_indent + 2, buffer);
1040
+ } else {
1041
+ hb_buffer_append(buffer, " ∅\n");
1042
+ }
1043
+ hb_buffer_append(buffer, "\n");
1044
+
1045
+
1046
+ pretty_print_label(hb_string("end_node"), indent, relative_indent, true, buffer);
1047
+
1048
+ if (erb_render_node->end_node) {
1049
+ hb_buffer_append(buffer, "\n");
1050
+ pretty_print_indent(buffer, indent);
1051
+ pretty_print_indent(buffer, relative_indent + 1);
1052
+
1053
+ hb_buffer_append(buffer, "└── ");
1054
+ ast_pretty_print_node((AST_NODE_T*) erb_render_node->end_node, indent, relative_indent + 2, buffer);
1055
+ } else {
1056
+ hb_buffer_append(buffer, " ∅\n");
1057
+ }
1058
+ hb_buffer_append(buffer, "\n");
1059
+
976
1060
  } break;
977
1061
 
978
- case AST_RUBY_STRICT_LOCAL_NODE: {
979
- const AST_RUBY_STRICT_LOCAL_NODE_T* ruby_strict_local_node = (AST_RUBY_STRICT_LOCAL_NODE_T*) node;
1062
+ case AST_RUBY_PARAMETER_NODE: {
1063
+ const AST_RUBY_PARAMETER_NODE_T* ruby_parameter_node = (AST_RUBY_PARAMETER_NODE_T*) node;
980
1064
 
981
1065
  pretty_print_errors(node, indent, relative_indent, false, buffer);
982
- pretty_print_token_property(ruby_strict_local_node->name, hb_string("name"), indent, relative_indent, false, buffer);
1066
+ pretty_print_token_property(ruby_parameter_node->name, hb_string("name"), indent, relative_indent, false, buffer);
983
1067
 
984
1068
  pretty_print_label(hb_string("default_value"), indent, relative_indent, false, buffer);
985
1069
 
986
- if (ruby_strict_local_node->default_value) {
1070
+ if (ruby_parameter_node->default_value) {
987
1071
  hb_buffer_append(buffer, "\n");
988
1072
  pretty_print_indent(buffer, indent);
989
1073
  pretty_print_indent(buffer, relative_indent + 1);
990
1074
 
991
1075
  hb_buffer_append(buffer, "└── ");
992
- ast_pretty_print_node((AST_NODE_T*) ruby_strict_local_node->default_value, indent, relative_indent + 2, buffer);
1076
+ ast_pretty_print_node((AST_NODE_T*) ruby_parameter_node->default_value, indent, relative_indent + 2, buffer);
993
1077
  } else {
994
1078
  hb_buffer_append(buffer, " ∅\n");
995
1079
  }
996
1080
  hb_buffer_append(buffer, "\n");
997
1081
 
998
- pretty_print_boolean_property(hb_string("required"), ruby_strict_local_node->required, indent, relative_indent, false, buffer);
999
- pretty_print_boolean_property(hb_string("double_splat"), ruby_strict_local_node->double_splat, indent, relative_indent, true, buffer);
1082
+ pretty_print_string_property(ruby_parameter_node->kind, hb_string("kind"), indent, relative_indent, false, buffer);
1083
+ pretty_print_boolean_property(hb_string("required"), ruby_parameter_node->required, indent, relative_indent, true, buffer);
1000
1084
  } break;
1001
1085
 
1002
1086
  case AST_ERB_STRICT_LOCALS_NODE: {