herb 0.9.2-arm-linux-gnu → 0.9.4-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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/config.yml +125 -0
  4. data/ext/herb/error_helpers.c +172 -2
  5. data/ext/herb/extconf.rb +6 -0
  6. data/ext/herb/extension.c +16 -2
  7. data/ext/herb/extension_helpers.c +6 -5
  8. data/ext/herb/extension_helpers.h +4 -4
  9. data/ext/herb/nodes.c +89 -3
  10. data/lib/herb/3.0/herb.so +0 -0
  11. data/lib/herb/3.1/herb.so +0 -0
  12. data/lib/herb/3.2/herb.so +0 -0
  13. data/lib/herb/3.3/herb.so +0 -0
  14. data/lib/herb/3.4/herb.so +0 -0
  15. data/lib/herb/4.0/herb.so +0 -0
  16. data/lib/herb/ast/erb_content_node.rb +32 -0
  17. data/lib/herb/ast/nodes.rb +244 -3
  18. data/lib/herb/cli.rb +12 -2
  19. data/lib/herb/engine/compiler.rb +166 -75
  20. data/lib/herb/engine/validators/security_validator.rb +40 -0
  21. data/lib/herb/engine.rb +3 -0
  22. data/lib/herb/errors.rb +268 -0
  23. data/lib/herb/parser_options.rb +7 -2
  24. data/lib/herb/project.rb +58 -17
  25. data/lib/herb/version.rb +1 -1
  26. data/lib/herb/visitor.rb +82 -0
  27. data/lib/herb.rb +1 -0
  28. data/sig/herb/ast/erb_content_node.rbs +13 -0
  29. data/sig/herb/ast/nodes.rbs +98 -2
  30. data/sig/herb/engine/compiler.rbs +31 -2
  31. data/sig/herb/engine/validators/security_validator.rbs +4 -0
  32. data/sig/herb/engine.rbs +3 -0
  33. data/sig/herb/errors.rbs +122 -0
  34. data/sig/herb/parser_options.rbs +6 -2
  35. data/sig/herb/visitor.rbs +12 -0
  36. data/sig/serialized_ast_errors.rbs +29 -0
  37. data/sig/serialized_ast_nodes.rbs +19 -0
  38. data/src/analyze/action_view/attribute_extraction_helpers.c +420 -91
  39. data/src/analyze/action_view/image_tag.c +87 -0
  40. data/src/analyze/action_view/javascript_include_tag.c +22 -12
  41. data/src/analyze/action_view/registry.c +6 -3
  42. data/src/analyze/action_view/tag.c +19 -2
  43. data/src/analyze/action_view/tag_helper_node_builders.c +105 -36
  44. data/src/analyze/action_view/tag_helpers.c +792 -44
  45. data/src/analyze/analyze.c +167 -13
  46. data/src/analyze/{helpers.c → analyze_helpers.c} +1 -1
  47. data/src/analyze/analyzed_ruby.c +1 -1
  48. data/src/analyze/builders.c +11 -8
  49. data/src/analyze/conditional_elements.c +6 -7
  50. data/src/analyze/conditional_open_tags.c +6 -7
  51. data/src/analyze/control_type.c +4 -2
  52. data/src/analyze/invalid_structures.c +5 -5
  53. data/src/analyze/missing_end.c +2 -2
  54. data/src/analyze/parse_errors.c +47 -6
  55. data/src/analyze/prism_annotate.c +7 -7
  56. data/src/analyze/render_nodes.c +6 -26
  57. data/src/analyze/strict_locals.c +651 -0
  58. data/src/analyze/transform.c +7 -0
  59. data/src/{ast_node.c → ast/ast_node.c} +8 -8
  60. data/src/{ast_nodes.c → ast/ast_nodes.c} +82 -11
  61. data/src/{ast_pretty_print.c → ast/ast_pretty_print.c} +113 -9
  62. data/src/{pretty_print.c → ast/pretty_print.c} +9 -9
  63. data/src/errors.c +398 -8
  64. data/src/extract.c +5 -5
  65. data/src/herb.c +15 -5
  66. data/src/include/analyze/action_view/attribute_extraction_helpers.h +3 -1
  67. data/src/include/analyze/action_view/tag_helper_handler.h +3 -3
  68. data/src/include/analyze/action_view/tag_helper_node_builders.h +34 -5
  69. data/src/include/analyze/action_view/tag_helpers.h +4 -3
  70. data/src/include/analyze/analyze.h +12 -5
  71. data/src/include/analyze/analyzed_ruby.h +2 -2
  72. data/src/include/analyze/builders.h +4 -4
  73. data/src/include/analyze/conditional_elements.h +2 -2
  74. data/src/include/analyze/conditional_open_tags.h +2 -2
  75. data/src/include/analyze/control_type.h +1 -1
  76. data/src/include/analyze/helpers.h +2 -2
  77. data/src/include/analyze/invalid_structures.h +1 -1
  78. data/src/include/analyze/prism_annotate.h +2 -2
  79. data/src/include/analyze/render_nodes.h +1 -1
  80. data/src/include/analyze/strict_locals.h +11 -0
  81. data/src/include/{ast_node.h → ast/ast_node.h} +4 -4
  82. data/src/include/{ast_nodes.h → ast/ast_nodes.h} +38 -14
  83. data/src/include/{ast_pretty_print.h → ast/ast_pretty_print.h} +3 -3
  84. data/src/include/{pretty_print.h → ast/pretty_print.h} +4 -4
  85. data/src/include/errors.h +65 -7
  86. data/src/include/extract.h +2 -2
  87. data/src/include/herb.h +5 -5
  88. data/src/include/{lex_helpers.h → lexer/lex_helpers.h} +5 -5
  89. data/src/include/{lexer.h → lexer/lexer.h} +1 -1
  90. data/src/include/{lexer_peek_helpers.h → lexer/lexer_peek_helpers.h} +2 -2
  91. data/src/include/{lexer_struct.h → lexer/lexer_struct.h} +2 -2
  92. data/src/include/{token.h → lexer/token.h} +3 -3
  93. data/src/include/{token_matchers.h → lexer/token_matchers.h} +1 -1
  94. data/src/include/{token_struct.h → lexer/token_struct.h} +3 -3
  95. data/src/include/{util → lib}/hb_foreach.h +1 -1
  96. data/src/include/{util → lib}/hb_string.h +5 -1
  97. data/src/include/{location.h → location/location.h} +1 -1
  98. data/src/include/parser/dot_notation.h +12 -0
  99. data/src/include/{parser.h → parser/parser.h} +11 -4
  100. data/src/include/{parser_helpers.h → parser/parser_helpers.h} +6 -6
  101. data/src/include/{prism_context.h → prism/prism_context.h} +2 -2
  102. data/src/include/{prism_helpers.h → prism/prism_helpers.h} +6 -6
  103. data/src/include/{html_util.h → util/html_util.h} +1 -1
  104. data/src/include/util/ruby_util.h +9 -0
  105. data/src/include/{utf8.h → util/utf8.h} +1 -1
  106. data/src/include/{util.h → util/util.h} +1 -1
  107. data/src/include/version.h +1 -1
  108. data/src/include/visitor.h +3 -3
  109. data/src/{lexer_peek_helpers.c → lexer/lexer_peek_helpers.c} +3 -3
  110. data/src/{token.c → lexer/token.c} +8 -8
  111. data/src/{token_matchers.c → lexer/token_matchers.c} +2 -2
  112. data/src/lexer.c +6 -6
  113. data/src/{util → lib}/hb_allocator.c +2 -2
  114. data/src/{util → lib}/hb_arena.c +1 -1
  115. data/src/{util → lib}/hb_arena_debug.c +2 -2
  116. data/src/{util → lib}/hb_array.c +2 -2
  117. data/src/{util → lib}/hb_buffer.c +2 -2
  118. data/src/{util → lib}/hb_narray.c +1 -1
  119. data/src/{util → lib}/hb_string.c +2 -2
  120. data/src/{location.c → location/location.c} +2 -2
  121. data/src/{position.c → location/position.c} +2 -2
  122. data/src/{range.c → location/range.c} +1 -1
  123. data/src/main.c +11 -11
  124. data/src/parser/dot_notation.c +100 -0
  125. data/src/{parser_match_tags.c → parser/match_tags.c} +34 -5
  126. data/src/{parser_helpers.c → parser/parser_helpers.c} +10 -10
  127. data/src/parser.c +68 -32
  128. data/src/{prism_helpers.c → prism/prism_helpers.c} +7 -7
  129. data/src/{ruby_parser.c → prism/ruby_parser.c} +1 -1
  130. data/src/{html_util.c → util/html_util.c} +4 -4
  131. data/src/{io.c → util/io.c} +3 -3
  132. data/src/util/ruby_util.c +42 -0
  133. data/src/{utf8.c → util/utf8.c} +2 -2
  134. data/src/{util.c → util/util.c} +4 -4
  135. data/src/visitor.c +35 -3
  136. data/templates/ext/herb/error_helpers.c.erb +2 -2
  137. data/templates/ext/herb/nodes.c.erb +1 -1
  138. data/templates/java/error_helpers.c.erb +1 -1
  139. data/templates/java/error_helpers.h.erb +2 -2
  140. data/templates/java/nodes.c.erb +4 -4
  141. data/templates/java/nodes.h.erb +1 -1
  142. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +4 -4
  143. data/templates/javascript/packages/node/extension/nodes.cpp.erb +4 -4
  144. data/templates/lib/herb/visitor.rb.erb +14 -0
  145. data/templates/src/analyze/missing_end.c.erb +2 -2
  146. data/templates/src/{ast_nodes.c.erb → ast/ast_nodes.c.erb} +9 -9
  147. data/templates/src/{ast_pretty_print.c.erb → ast/ast_pretty_print.c.erb} +8 -8
  148. data/templates/src/errors.c.erb +8 -8
  149. data/templates/src/include/{ast_nodes.h.erb → ast/ast_nodes.h.erb} +11 -12
  150. data/templates/src/include/{ast_pretty_print.h.erb → ast/ast_pretty_print.h.erb} +2 -2
  151. data/templates/src/include/errors.h.erb +7 -7
  152. data/templates/src/{parser_match_tags.c.erb → parser/match_tags.c.erb} +4 -4
  153. data/templates/src/visitor.c.erb +3 -3
  154. data/templates/wasm/error_helpers.cpp.erb +4 -4
  155. data/templates/wasm/nodes.cpp.erb +5 -5
  156. metadata +76 -68
  157. data/src/include/element_source.h +0 -10
  158. /data/src/include/{util → lib}/hb_allocator.h +0 -0
  159. /data/src/include/{util → lib}/hb_arena.h +0 -0
  160. /data/src/include/{util → lib}/hb_arena_debug.h +0 -0
  161. /data/src/include/{util → lib}/hb_array.h +0 -0
  162. /data/src/include/{util → lib}/hb_buffer.h +0 -0
  163. /data/src/include/{util → lib}/hb_narray.h +0 -0
  164. /data/src/include/{util → lib}/string.h +0 -0
  165. /data/src/include/{position.h → location/position.h} +0 -0
  166. /data/src/include/{range.h → location/range.h} +0 -0
  167. /data/src/include/{herb_prism_node.h → prism/herb_prism_node.h} +0 -0
  168. /data/src/include/{prism_serialized.h → prism/prism_serialized.h} +0 -0
  169. /data/src/include/{ruby_parser.h → prism/ruby_parser.h} +0 -0
  170. /data/src/include/{io.h → util/io.h} +0 -0
  171. /data/templates/src/include/{util → lib}/hb_foreach.h.erb +0 -0
@@ -9,16 +9,17 @@
9
9
  #include "../include/analyze/helpers.h"
10
10
  #include "../include/analyze/invalid_structures.h"
11
11
  #include "../include/analyze/render_nodes.h"
12
- #include "../include/ast_node.h"
13
- #include "../include/ast_nodes.h"
12
+ #include "../include/analyze/strict_locals.h"
13
+ #include "../include/ast/ast_node.h"
14
+ #include "../include/ast/ast_nodes.h"
14
15
  #include "../include/errors.h"
15
- #include "../include/location.h"
16
- #include "../include/parser.h"
17
- #include "../include/position.h"
18
- #include "../include/token_struct.h"
19
- #include "../include/util/hb_array.h"
20
- #include "../include/util/hb_string.h"
21
- #include "../include/util/string.h"
16
+ #include "../include/lexer/token_struct.h"
17
+ #include "../include/lib/hb_array.h"
18
+ #include "../include/lib/hb_string.h"
19
+ #include "../include/lib/string.h"
20
+ #include "../include/location/location.h"
21
+ #include "../include/location/position.h"
22
+ #include "../include/parser/parser.h"
22
23
  #include "../include/visitor.h"
23
24
 
24
25
  #include <prism.h>
@@ -74,8 +75,7 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) {
74
75
 
75
76
  hb_string_T opening = erb_content_node->tag_opening->value;
76
77
 
77
- if (!hb_string_equals(opening, hb_string("<%%")) && !hb_string_equals(opening, hb_string("<%%="))
78
- && !hb_string_equals(opening, hb_string("<%#")) && !hb_string_equals(opening, hb_string("<%graphql"))) {
78
+ if (!hb_string_equals(opening, hb_string("<%#")) && !hb_string_equals(opening, hb_string("<%graphql"))) {
79
79
  analyzed_ruby_T* analyzed = herb_analyze_ruby(erb_content_node->content->value);
80
80
 
81
81
  erb_content_node->parsed = true;
@@ -252,6 +252,14 @@ static size_t process_begin_structure(
252
252
  analyze_ruby_context_T* context
253
253
  );
254
254
 
255
+ static size_t process_block_structure(
256
+ AST_NODE_T* node,
257
+ hb_array_T* array,
258
+ size_t index,
259
+ hb_array_T* output_array,
260
+ analyze_ruby_context_T* context
261
+ );
262
+
255
263
  static size_t process_generic_structure(
256
264
  AST_NODE_T* node,
257
265
  hb_array_T* array,
@@ -272,8 +280,8 @@ static size_t process_control_structure(
272
280
  switch (initial_type) {
273
281
  case CONTROL_TYPE_CASE:
274
282
  case CONTROL_TYPE_CASE_MATCH: return process_case_structure(node, array, index, output_array, context);
275
-
276
283
  case CONTROL_TYPE_BEGIN: return process_begin_structure(node, array, index, output_array, context);
284
+ case CONTROL_TYPE_BLOCK: return process_block_structure(node, array, index, output_array, context);
277
285
 
278
286
  default: return process_generic_structure(node, array, index, output_array, context, initial_type);
279
287
  }
@@ -630,6 +638,126 @@ static size_t process_begin_structure(
630
638
  return index;
631
639
  }
632
640
 
641
+ static size_t process_block_structure(
642
+ AST_NODE_T* node,
643
+ hb_array_T* array,
644
+ size_t index,
645
+ hb_array_T* output_array,
646
+ analyze_ruby_context_T* context
647
+ ) {
648
+ hb_allocator_T* allocator = context->allocator;
649
+ AST_ERB_CONTENT_NODE_T* erb_node = get_erb_content_at(array, index);
650
+ if (!erb_node) { return index; }
651
+ hb_array_T* children = hb_array_init(8, allocator);
652
+
653
+ index++;
654
+ index = process_block_children(node, array, index, children, context, CONTROL_TYPE_BLOCK);
655
+
656
+ AST_ERB_RESCUE_NODE_T* rescue_clause = NULL;
657
+ AST_ERB_ELSE_NODE_T* else_clause = NULL;
658
+ AST_ERB_ENSURE_NODE_T* ensure_clause = NULL;
659
+
660
+ control_type_t next_type = CONTROL_TYPE_UNKNOWN;
661
+ AST_ERB_CONTENT_NODE_T* next_erb = NULL;
662
+
663
+ if (peek_control_type(array, index, &next_type, &next_erb) && next_type == CONTROL_TYPE_RESCUE) {
664
+ AST_NODE_T* rescue_node = NULL;
665
+ index = process_subsequent_block(node, array, index, &rescue_node, context, CONTROL_TYPE_BLOCK);
666
+ rescue_clause = (AST_ERB_RESCUE_NODE_T*) rescue_node;
667
+ }
668
+
669
+ if (peek_control_type(array, index, &next_type, &next_erb) && next_type == CONTROL_TYPE_ELSE) {
670
+ hb_array_T* else_children = hb_array_init(8, allocator);
671
+ index++;
672
+
673
+ index = process_block_children(node, array, index, else_children, context, CONTROL_TYPE_BLOCK);
674
+
675
+ hb_array_T* else_errors = next_erb->base.errors;
676
+ next_erb->base.errors = NULL;
677
+
678
+ else_clause = ast_erb_else_node_init(
679
+ next_erb->tag_opening,
680
+ next_erb->content,
681
+ next_erb->tag_closing,
682
+ else_children,
683
+ next_erb->tag_opening->location.start,
684
+ erb_content_end_position(next_erb),
685
+ else_errors,
686
+ allocator
687
+ );
688
+
689
+ ast_node_free((AST_NODE_T*) next_erb, allocator);
690
+ }
691
+
692
+ if (peek_control_type(array, index, &next_type, &next_erb) && next_type == CONTROL_TYPE_ENSURE) {
693
+ hb_array_T* ensure_children = hb_array_init(8, allocator);
694
+ index++;
695
+
696
+ const control_type_t ensure_stop[] = { CONTROL_TYPE_END, CONTROL_TYPE_BLOCK_CLOSE };
697
+ collect_children_until(array, &index, ensure_children, ensure_stop, sizeof(ensure_stop) / sizeof(ensure_stop[0]));
698
+
699
+ hb_array_T* ensure_errors = next_erb->base.errors;
700
+ next_erb->base.errors = NULL;
701
+
702
+ ensure_clause = ast_erb_ensure_node_init(
703
+ next_erb->tag_opening,
704
+ next_erb->content,
705
+ next_erb->tag_closing,
706
+ ensure_children,
707
+ next_erb->tag_opening->location.start,
708
+ erb_content_end_position(next_erb),
709
+ ensure_errors,
710
+ allocator
711
+ );
712
+
713
+ ast_node_free((AST_NODE_T*) next_erb, allocator);
714
+ }
715
+
716
+ const control_type_t end_types[] = { CONTROL_TYPE_BLOCK_CLOSE, CONTROL_TYPE_END };
717
+ AST_ERB_END_NODE_T* end_node =
718
+ consume_end_node(array, &index, end_types, sizeof(end_types) / sizeof(end_types[0]), allocator);
719
+
720
+ position_T start_position = erb_node->tag_opening->location.start;
721
+ position_T end_position = erb_content_end_position(erb_node);
722
+
723
+ if (end_node) {
724
+ end_position = end_node->base.location.end;
725
+ } else if (ensure_clause) {
726
+ end_position = ensure_clause->base.location.end;
727
+ } else if (else_clause) {
728
+ end_position = else_clause->base.location.end;
729
+ } else if (rescue_clause) {
730
+ end_position = rescue_clause->base.location.end;
731
+ } else if (hb_array_size(children) > 0) {
732
+ AST_NODE_T* last_child = hb_array_last(children);
733
+ end_position = last_child->location.end;
734
+ }
735
+
736
+ hb_array_T* block_errors = erb_node->base.errors;
737
+ erb_node->base.errors = NULL;
738
+
739
+ AST_ERB_BLOCK_NODE_T* block_node = ast_erb_block_node_init(
740
+ erb_node->tag_opening,
741
+ erb_node->content,
742
+ erb_node->tag_closing,
743
+ HERB_PRISM_NODE_EMPTY,
744
+ children,
745
+ rescue_clause,
746
+ else_clause,
747
+ ensure_clause,
748
+ end_node,
749
+ start_position,
750
+ end_position,
751
+ block_errors,
752
+ allocator
753
+ );
754
+
755
+ ast_node_free((AST_NODE_T*) erb_node, allocator);
756
+ hb_array_append(output_array, (AST_NODE_T*) block_node);
757
+
758
+ return index;
759
+ }
760
+
633
761
  static size_t process_generic_structure(
634
762
  AST_NODE_T* node,
635
763
  hb_array_T* array,
@@ -796,6 +924,28 @@ static size_t process_block_children(
796
924
  return index;
797
925
  }
798
926
 
927
+ hb_array_T* get_node_children_array(const AST_NODE_T* node) {
928
+ if (!node) { return NULL; }
929
+
930
+ switch (node->type) {
931
+ case AST_DOCUMENT_NODE: return ((AST_DOCUMENT_NODE_T*) node)->children;
932
+ case AST_HTML_ELEMENT_NODE: return ((AST_HTML_ELEMENT_NODE_T*) node)->body;
933
+ case AST_ERB_BLOCK_NODE: return ((AST_ERB_BLOCK_NODE_T*) node)->body;
934
+ case AST_ERB_IF_NODE: return ((AST_ERB_IF_NODE_T*) node)->statements;
935
+ case AST_ERB_UNLESS_NODE: return ((AST_ERB_UNLESS_NODE_T*) node)->statements;
936
+ case AST_ERB_ELSE_NODE: return ((AST_ERB_ELSE_NODE_T*) node)->statements;
937
+ case AST_ERB_WHILE_NODE: return ((AST_ERB_WHILE_NODE_T*) node)->statements;
938
+ case AST_ERB_UNTIL_NODE: return ((AST_ERB_UNTIL_NODE_T*) node)->statements;
939
+ case AST_ERB_FOR_NODE: return ((AST_ERB_FOR_NODE_T*) node)->statements;
940
+ case AST_ERB_BEGIN_NODE: return ((AST_ERB_BEGIN_NODE_T*) node)->statements;
941
+ case AST_ERB_RESCUE_NODE: return ((AST_ERB_RESCUE_NODE_T*) node)->statements;
942
+ case AST_ERB_ENSURE_NODE: return ((AST_ERB_ENSURE_NODE_T*) node)->statements;
943
+ case AST_ERB_CASE_NODE: return ((AST_ERB_CASE_NODE_T*) node)->children;
944
+ case AST_ERB_WHEN_NODE: return ((AST_ERB_WHEN_NODE_T*) node)->statements;
945
+ default: return NULL;
946
+ }
947
+ }
948
+
799
949
  hb_array_T* rewrite_node_array(AST_NODE_T* node, hb_array_T* array, analyze_ruby_context_T* context) {
800
950
  hb_allocator_T* allocator = context->allocator;
801
951
  hb_array_T* new_array = hb_array_init(hb_array_size(array), allocator);
@@ -862,6 +1012,10 @@ void herb_analyze_parse_tree(
862
1012
 
863
1013
  if (options && options->render_nodes) { herb_visit_node((AST_NODE_T*) document, transform_render_nodes, &context); }
864
1014
 
1015
+ if (options && options->strict_locals) {
1016
+ herb_visit_node((AST_NODE_T*) document, transform_strict_locals_nodes, &context);
1017
+ }
1018
+
865
1019
  if (options && options->action_view_helpers) {
866
1020
  herb_visit_node((AST_NODE_T*) document, transform_tag_helper_nodes, &context);
867
1021
  }
@@ -877,7 +1031,7 @@ void herb_analyze_parse_tree(
877
1031
 
878
1032
  herb_visit_node((AST_NODE_T*) document, detect_invalid_erb_structures, &invalid_context);
879
1033
 
880
- herb_analyze_parse_errors(document, source, allocator);
1034
+ herb_analyze_parse_errors(document, source, options, allocator);
881
1035
 
882
1036
  herb_parser_match_html_tags_post_analyze(document, options, allocator);
883
1037
 
@@ -3,7 +3,7 @@
3
3
  #include <string.h>
4
4
 
5
5
  #include "../include/analyze/analyzed_ruby.h"
6
- #include "../include/util/string.h"
6
+ #include "../include/lib/string.h"
7
7
 
8
8
  bool has_if_node(analyzed_ruby_T* analyzed) {
9
9
  return analyzed && analyzed->if_node_count > 0;
@@ -1,5 +1,5 @@
1
1
  #include "../include/analyze/analyzed_ruby.h"
2
- #include "../include/util/hb_string.h"
2
+ #include "../include/lib/hb_string.h"
3
3
 
4
4
  #include <prism.h>
5
5
  #include <string.h>
@@ -1,13 +1,13 @@
1
1
  #include "../include/analyze/builders.h"
2
2
  #include "../include/analyze/analyze.h"
3
- #include "../include/ast_nodes.h"
4
- #include "../include/location.h"
5
- #include "../include/position.h"
6
- #include "../include/prism_helpers.h"
7
- #include "../include/token_struct.h"
8
- #include "../include/util/hb_allocator.h"
9
- #include "../include/util/hb_array.h"
10
- #include "../include/util/hb_string.h"
3
+ #include "../include/ast/ast_nodes.h"
4
+ #include "../include/lexer/token_struct.h"
5
+ #include "../include/lib/hb_allocator.h"
6
+ #include "../include/lib/hb_array.h"
7
+ #include "../include/lib/hb_string.h"
8
+ #include "../include/location/location.h"
9
+ #include "../include/location/position.h"
10
+ #include "../include/prism/prism_helpers.h"
11
11
 
12
12
  #include <stddef.h>
13
13
  #include <string.h>
@@ -322,6 +322,9 @@ static AST_NODE_T* build_block_node(control_builder_context_T* context) {
322
322
  context->tag_closing,
323
323
  HERB_PRISM_NODE_EMPTY,
324
324
  context->children,
325
+ NULL,
326
+ NULL,
327
+ NULL,
325
328
  context->end_node,
326
329
  context->start_position,
327
330
  context->end_position,
@@ -1,11 +1,10 @@
1
1
  #include "../include/analyze/conditional_elements.h"
2
- #include "../include/ast_nodes.h"
3
- #include "../include/element_source.h"
2
+ #include "../include/ast/ast_nodes.h"
4
3
  #include "../include/errors.h"
5
- #include "../include/token_struct.h"
6
- #include "../include/util/hb_allocator.h"
7
- #include "../include/util/hb_array.h"
8
- #include "../include/util/hb_string.h"
4
+ #include "../include/lexer/token_struct.h"
5
+ #include "../include/lib/hb_allocator.h"
6
+ #include "../include/lib/hb_array.h"
7
+ #include "../include/lib/hb_string.h"
9
8
  #include "../include/visitor.h"
10
9
 
11
10
  #include <stdbool.h>
@@ -365,7 +364,7 @@ static void rewrite_conditional_elements(hb_array_T* nodes, hb_array_T* document
365
364
  (AST_NODE_T*) close_tag,
366
365
  node,
367
366
  matched_open->open_tag->tag_name,
368
- ELEMENT_SOURCE_HTML,
367
+ hb_string("HTML"),
369
368
  start_position,
370
369
  end_position,
371
370
  errors,
@@ -1,11 +1,10 @@
1
1
  #include "../include/analyze/conditional_open_tags.h"
2
- #include "../include/ast_nodes.h"
3
- #include "../include/element_source.h"
2
+ #include "../include/ast/ast_nodes.h"
4
3
  #include "../include/errors.h"
5
- #include "../include/token_struct.h"
6
- #include "../include/util/hb_allocator.h"
7
- #include "../include/util/hb_array.h"
8
- #include "../include/util/hb_string.h"
4
+ #include "../include/lexer/token_struct.h"
5
+ #include "../include/lib/hb_allocator.h"
6
+ #include "../include/lib/hb_array.h"
7
+ #include "../include/lib/hb_string.h"
9
8
  #include "../include/visitor.h"
10
9
 
11
10
  #include <stdbool.h>
@@ -409,7 +408,7 @@ static void rewrite_conditional_open_tags(hb_array_T* nodes, hb_array_T* documen
409
408
  body,
410
409
  (AST_NODE_T*) close_tag,
411
410
  false,
412
- ELEMENT_SOURCE_HTML,
411
+ hb_string("HTML"),
413
412
  start_position,
414
413
  end_position,
415
414
  element_errors,
@@ -2,7 +2,7 @@
2
2
  #include "../include/analyze/analyze.h"
3
3
  #include "../include/analyze/analyzed_ruby.h"
4
4
  #include "../include/analyze/helpers.h"
5
- #include "../include/ast_node.h"
5
+ #include "../include/ast/ast_node.h"
6
6
 
7
7
  #include <prism.h>
8
8
  #include <stdbool.h>
@@ -213,6 +213,7 @@ bool is_subsequent_type(control_type_t parent_type, control_type_t child_type) {
213
213
  case CONTROL_TYPE_CASE:
214
214
  case CONTROL_TYPE_CASE_MATCH: return child_type == CONTROL_TYPE_WHEN || child_type == CONTROL_TYPE_ELSE;
215
215
  case CONTROL_TYPE_BEGIN:
216
+ case CONTROL_TYPE_BLOCK:
216
217
  return child_type == CONTROL_TYPE_RESCUE || child_type == CONTROL_TYPE_ELSE || child_type == CONTROL_TYPE_ENSURE;
217
218
  case CONTROL_TYPE_RESCUE: return child_type == CONTROL_TYPE_RESCUE;
218
219
  case CONTROL_TYPE_UNLESS: return child_type == CONTROL_TYPE_ELSE;
@@ -227,7 +228,8 @@ bool is_terminator_type(control_type_t parent_type, control_type_t child_type) {
227
228
  switch (parent_type) {
228
229
  case CONTROL_TYPE_WHEN: return child_type == CONTROL_TYPE_WHEN || child_type == CONTROL_TYPE_ELSE;
229
230
  case CONTROL_TYPE_IN: return child_type == CONTROL_TYPE_IN || child_type == CONTROL_TYPE_ELSE;
230
- case CONTROL_TYPE_BLOCK: return child_type == CONTROL_TYPE_BLOCK_CLOSE;
231
+ case CONTROL_TYPE_BLOCK:
232
+ return child_type == CONTROL_TYPE_BLOCK_CLOSE || is_subsequent_type(parent_type, child_type);
231
233
 
232
234
  default: return is_subsequent_type(parent_type, child_type);
233
235
  }
@@ -2,12 +2,12 @@
2
2
  #include "../include/analyze/analyze.h"
3
3
  #include "../include/analyze/analyzed_ruby.h"
4
4
  #include "../include/analyze/helpers.h"
5
- #include "../include/ast_node.h"
6
- #include "../include/ast_nodes.h"
5
+ #include "../include/ast/ast_node.h"
6
+ #include "../include/ast/ast_nodes.h"
7
7
  #include "../include/errors.h"
8
- #include "../include/token_struct.h"
9
- #include "../include/util/hb_array.h"
10
- #include "../include/util/hb_string.h"
8
+ #include "../include/lexer/token_struct.h"
9
+ #include "../include/lib/hb_array.h"
10
+ #include "../include/lib/hb_string.h"
11
11
  #include "../include/visitor.h"
12
12
 
13
13
  #include <stdbool.h>
@@ -3,8 +3,8 @@
3
3
 
4
4
  #include "../include/analyze/helpers.h"
5
5
  #include "../include/errors.h"
6
- #include "../include/util/hb_allocator.h"
7
- #include "../include/util/hb_string.h"
6
+ #include "../include/lib/hb_allocator.h"
7
+ #include "../include/lib/hb_string.h"
8
8
 
9
9
 
10
10
  void check_erb_node_for_missing_end(const AST_NODE_T* node, hb_allocator_T* allocator) {
@@ -1,16 +1,47 @@
1
1
  #include "../include/analyze/analyze.h"
2
- #include "../include/ast_node.h"
3
- #include "../include/ast_nodes.h"
2
+ #include "../include/ast/ast_node.h"
3
+ #include "../include/ast/ast_nodes.h"
4
4
  #include "../include/errors.h"
5
5
  #include "../include/extract.h"
6
- #include "../include/prism_helpers.h"
7
- #include "../include/util/hb_allocator.h"
8
- #include "../include/util/hb_string.h"
6
+ #include "../include/lib/hb_allocator.h"
7
+ #include "../include/lib/hb_string.h"
8
+ #include "../include/prism/prism_helpers.h"
9
9
 
10
10
  #include <prism.h>
11
11
  #include <stdlib.h>
12
12
  #include <string.h>
13
13
 
14
+ static bool document_has_anonymous_keyword_rest(AST_DOCUMENT_NODE_T* document) {
15
+ if (!document || !document->children) { return false; }
16
+
17
+ for (size_t index = 0; index < hb_array_size(document->children); index++) {
18
+ AST_NODE_T* child = hb_array_get(document->children, index);
19
+ if (!child || child->type != AST_ERB_STRICT_LOCALS_NODE) { continue; }
20
+
21
+ AST_ERB_STRICT_LOCALS_NODE_T* strict_locals_node = (AST_ERB_STRICT_LOCALS_NODE_T*) child;
22
+ if (!strict_locals_node->locals) { continue; }
23
+
24
+ for (size_t local_index = 0; local_index < hb_array_size(strict_locals_node->locals); local_index++) {
25
+ AST_RUBY_STRICT_LOCAL_NODE_T* local = hb_array_get(strict_locals_node->locals, local_index);
26
+ if (local && local->double_splat && local->name == NULL) { return true; }
27
+ }
28
+ }
29
+
30
+ return false;
31
+ }
32
+
33
+ static bool should_skip_forwarding_error(
34
+ const pm_diagnostic_t* error,
35
+ bool strict_locals_enabled,
36
+ bool has_anonymous_keyword_rest
37
+ ) {
38
+ if (error->diag_id != PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR) { return false; }
39
+
40
+ if (!strict_locals_enabled) { return true; }
41
+
42
+ return has_anonymous_keyword_rest;
43
+ }
44
+
14
45
  static void parse_erb_content_errors(AST_NODE_T* erb_node, const char* source, hb_allocator_T* allocator) {
15
46
  if (!erb_node || erb_node->type != AST_ERB_CONTENT_NODE) { return; }
16
47
  AST_ERB_CONTENT_NODE_T* content_node = (AST_ERB_CONTENT_NODE_T*) erb_node;
@@ -45,11 +76,19 @@ static void parse_erb_content_errors(AST_NODE_T* erb_node, const char* source, h
45
76
  free(content);
46
77
  }
47
78
 
48
- void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source, hb_allocator_T* allocator) {
79
+ void herb_analyze_parse_errors(
80
+ AST_DOCUMENT_NODE_T* document,
81
+ const char* source,
82
+ const parser_options_T* parser_options,
83
+ hb_allocator_T* allocator
84
+ ) {
49
85
  char* extracted_ruby = herb_extract_ruby_with_semicolons(source, allocator);
50
86
 
51
87
  if (!extracted_ruby) { return; }
52
88
 
89
+ bool strict_locals_enabled = parser_options && parser_options->strict_locals;
90
+ bool has_anonymous_keyword_rest = strict_locals_enabled && document_has_anonymous_keyword_rest(document);
91
+
53
92
  pm_parser_t parser;
54
93
  pm_options_t options = { 0, .partial_script = true };
55
94
  pm_parser_init(&parser, (const uint8_t*) extracted_ruby, strlen(extracted_ruby), &options);
@@ -58,6 +97,8 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source
58
97
 
59
98
  for (const pm_diagnostic_t* error = (const pm_diagnostic_t*) parser.error_list.head; error != NULL;
60
99
  error = (const pm_diagnostic_t*) error->node.next) {
100
+ if (should_skip_forwarding_error(error, strict_locals_enabled, has_anonymous_keyword_rest)) { continue; }
101
+
61
102
  size_t error_offset = (size_t) (error->location.start - parser.start);
62
103
 
63
104
  if (strstr(error->message, "unexpected ';'") != NULL) {
@@ -1,12 +1,12 @@
1
1
  #include "../include/analyze/prism_annotate.h"
2
- #include "../include/ast_node.h"
3
- #include "../include/ast_nodes.h"
2
+ #include "../include/ast/ast_node.h"
3
+ #include "../include/ast/ast_nodes.h"
4
4
  #include "../include/extract.h"
5
- #include "../include/herb_prism_node.h"
6
- #include "../include/prism_context.h"
7
- #include "../include/util/hb_allocator.h"
8
- #include "../include/util/hb_buffer.h"
9
- #include "../include/util/hb_narray.h"
5
+ #include "../include/lib/hb_allocator.h"
6
+ #include "../include/lib/hb_buffer.h"
7
+ #include "../include/lib/hb_narray.h"
8
+ #include "../include/prism/herb_prism_node.h"
9
+ #include "../include/prism/prism_context.h"
10
10
  #include "../include/visitor.h"
11
11
 
12
12
  #include <prism.h>
@@ -2,12 +2,12 @@
2
2
  #include "../include/analyze/action_view/tag_helper_node_builders.h"
3
3
  #include "../include/analyze/action_view/tag_helpers.h"
4
4
  #include "../include/analyze/analyze.h"
5
- #include "../include/ast_nodes.h"
5
+ #include "../include/ast/ast_nodes.h"
6
6
  #include "../include/errors.h"
7
- #include "../include/util/hb_allocator.h"
8
- #include "../include/util/hb_array.h"
9
- #include "../include/util/hb_string.h"
10
- #include "../include/util/string.h"
7
+ #include "../include/lib/hb_allocator.h"
8
+ #include "../include/lib/hb_array.h"
9
+ #include "../include/lib/hb_string.h"
10
+ #include "../include/lib/string.h"
11
11
  #include "../include/visitor.h"
12
12
 
13
13
  #include <prism.h>
@@ -727,27 +727,7 @@ static void transform_render_nodes_in_array(hb_array_T* array, analyze_ruby_cont
727
727
  static void transform_render_in_node(const AST_NODE_T* node, analyze_ruby_context_T* context) {
728
728
  if (!node || !context) { return; }
729
729
 
730
- hb_array_T* array = NULL;
731
-
732
- switch (node->type) {
733
- case AST_DOCUMENT_NODE: array = ((AST_DOCUMENT_NODE_T*) node)->children; break;
734
- case AST_HTML_ELEMENT_NODE: array = ((AST_HTML_ELEMENT_NODE_T*) node)->body; break;
735
- case AST_ERB_BLOCK_NODE: array = ((AST_ERB_BLOCK_NODE_T*) node)->body; break;
736
- case AST_ERB_IF_NODE: array = ((AST_ERB_IF_NODE_T*) node)->statements; break;
737
- case AST_ERB_UNLESS_NODE: array = ((AST_ERB_UNLESS_NODE_T*) node)->statements; break;
738
- case AST_ERB_ELSE_NODE: array = ((AST_ERB_ELSE_NODE_T*) node)->statements; break;
739
- case AST_ERB_WHILE_NODE: array = ((AST_ERB_WHILE_NODE_T*) node)->statements; break;
740
- case AST_ERB_UNTIL_NODE: array = ((AST_ERB_UNTIL_NODE_T*) node)->statements; break;
741
- case AST_ERB_FOR_NODE: array = ((AST_ERB_FOR_NODE_T*) node)->statements; break;
742
- case AST_ERB_BEGIN_NODE: array = ((AST_ERB_BEGIN_NODE_T*) node)->statements; break;
743
- case AST_ERB_RESCUE_NODE: array = ((AST_ERB_RESCUE_NODE_T*) node)->statements; break;
744
- case AST_ERB_ENSURE_NODE: array = ((AST_ERB_ENSURE_NODE_T*) node)->statements; break;
745
- case AST_ERB_CASE_NODE: array = ((AST_ERB_CASE_NODE_T*) node)->children; break;
746
- case AST_ERB_WHEN_NODE: array = ((AST_ERB_WHEN_NODE_T*) node)->statements; break;
747
- default: return;
748
- }
749
-
750
- transform_render_nodes_in_array(array, context);
730
+ transform_render_nodes_in_array(get_node_children_array(node), context);
751
731
  }
752
732
 
753
733
  bool transform_render_nodes(const AST_NODE_T* node, void* data) {