herb 0.11.1 → 0.11.2

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 (247) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/config.yml +6 -0
  4. data/ext/herb/extconf.rb +8 -31
  5. data/ext/herb/nodes.c +75 -75
  6. data/ext/herb/parser_options_helpers.c +26 -0
  7. data/lib/herb/analysis/partial_index.rb +1 -1
  8. data/lib/herb/analysis/partial_resolution.rb +27 -0
  9. data/lib/herb/ast/helpers.rb +1 -1
  10. data/lib/herb/configuration.rb +11 -1
  11. data/lib/herb/dev/classifier.rb +1 -1
  12. data/lib/herb/engine/compiler.rb +5 -8
  13. data/lib/herb/engine/slots/dynamics_compiler.rb +53 -14
  14. data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
  15. data/lib/herb/engine/slots/visitor.rb +32 -4
  16. data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
  17. data/lib/herb/parser_options.rb +6 -3
  18. data/lib/herb/project.rb +19 -8
  19. data/lib/herb/version.rb +1 -1
  20. data/lib/herb.rb +1 -1
  21. data/sig/herb/analysis/partial_resolution.rbs +8 -0
  22. data/sig/herb/configuration.rbs +3 -0
  23. data/sig/herb/engine/slots/dynamics_compiler.rbs +24 -7
  24. data/sig/herb/engine/slots/visitor.rbs +14 -0
  25. data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
  26. data/sig/herb/parser_options.rbs +6 -4
  27. data/sig/herb.rbs +2 -2
  28. data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
  29. data/src/analyze/action_view/generated_handlers.c +36 -36
  30. data/src/analyze/action_view/image_tag.c +7 -3
  31. data/src/analyze/action_view/javascript_include_tag.c +6 -3
  32. data/src/analyze/action_view/link_to.c +23 -23
  33. data/src/analyze/action_view/registry.c +7 -3
  34. data/src/analyze/action_view/tag_helper_node_builders.c +6 -13
  35. data/src/analyze/action_view/tag_helpers.c +139 -90
  36. data/src/analyze/action_view/turbo_frame_tag.c +5 -4
  37. data/src/analyze/analyze.c +35 -19
  38. data/src/analyze/analyze_helpers.c +161 -188
  39. data/src/analyze/analyzed_ruby.c +8 -7
  40. data/src/analyze/control_type.c +29 -22
  41. data/src/analyze/herb_directives.c +16 -20
  42. data/src/analyze/iteration_nodes.c +69 -24
  43. data/src/analyze/parse_errors.c +32 -22
  44. data/src/analyze/postfix_conditionals.c +23 -13
  45. data/src/analyze/prism_annotate.c +29 -28
  46. data/src/analyze/render_nodes.c +51 -41
  47. data/src/analyze/strict_locals.c +14 -15
  48. data/src/analyze/ternary_conditionals.c +14 -10
  49. data/src/herb.c +10 -8
  50. data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
  51. data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
  52. data/src/include/analyze/action_view/tag_helpers.h +1 -1
  53. data/src/include/analyze/analyze.h +3 -2
  54. data/src/include/analyze/analyzed_ruby.h +4 -2
  55. data/src/include/analyze/helpers.h +6 -6
  56. data/src/include/herb.h +3 -2
  57. data/src/include/parser/parser_options.h +5 -0
  58. data/src/include/prism/prism_context.h +12 -12
  59. data/src/include/prism/prism_helpers.h +30 -0
  60. data/src/include/prism_version.h +11 -0
  61. data/src/include/version.h +1 -1
  62. data/src/parser/parser_helpers.c +1 -2
  63. data/src/parser.c +6 -7
  64. data/src/parser_options_defaults.c +1 -0
  65. data/src/prism/prism_helpers.c +84 -50
  66. data/src/prism/ruby_parser.c +20 -20
  67. data/templates/ext/herb/nodes.c.erb +5 -5
  68. data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
  69. data/templates/java/nodes.c.erb +6 -6
  70. data/templates/java/parser_options_helpers.c.erb +41 -2
  71. data/templates/java/parser_options_helpers.h.erb +2 -1
  72. data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
  73. data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
  74. data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
  75. data/templates/lib/herb/parser_options.rb.erb +1 -1
  76. data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
  77. data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
  78. data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
  79. data/templates/src/include/parser/parser_options.h.erb +10 -0
  80. data/templates/src/include/prism_version.h.erb +17 -0
  81. data/templates/src/parser_options_defaults.c.erb +1 -1
  82. data/templates/template.rb +17 -2
  83. data/templates/wasm/nodes.cpp.erb +5 -5
  84. data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
  85. data/vendor/prism/Rakefile +76 -7
  86. data/vendor/prism/config.yml +174 -161
  87. data/vendor/prism/include/prism/arena.h +45 -0
  88. data/vendor/prism/include/prism/arena.hpp +42 -0
  89. data/vendor/prism/include/prism/ast.h +2738 -611
  90. data/vendor/prism/include/prism/ast.hpp +641 -0
  91. data/vendor/prism/include/prism/buffer.h +60 -0
  92. data/vendor/prism/include/prism/buffer.hpp +55 -0
  93. data/vendor/prism/include/prism/comments.h +72 -0
  94. data/vendor/prism/include/prism/compiler/accel.h +26 -0
  95. data/vendor/prism/include/prism/compiler/align.h +36 -0
  96. data/vendor/prism/include/prism/compiler/assume.h +25 -0
  97. data/vendor/prism/include/prism/compiler/branch.h +26 -0
  98. data/vendor/prism/include/prism/compiler/bswap.h +46 -0
  99. data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
  100. data/vendor/prism/include/prism/compiler/endianness.h +34 -0
  101. data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
  102. data/vendor/prism/include/prism/compiler/exported.h +24 -0
  103. data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
  104. data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
  105. data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
  106. data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
  107. data/vendor/prism/include/prism/compiler/format.h +27 -0
  108. data/vendor/prism/include/prism/compiler/inline.h +17 -0
  109. data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
  110. data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
  111. data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
  112. data/vendor/prism/include/prism/compiler/unused.h +18 -0
  113. data/vendor/prism/include/prism/constant_pool.h +106 -0
  114. data/vendor/prism/include/prism/diagnostic.h +55 -402
  115. data/vendor/prism/include/prism/errors_format.h +61 -0
  116. data/vendor/prism/include/prism/excludes.h +29 -0
  117. data/vendor/prism/include/prism/integer.h +41 -0
  118. data/vendor/prism/include/prism/internal/allocator.h +68 -0
  119. data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
  120. data/vendor/prism/include/prism/internal/arena.h +108 -0
  121. data/vendor/prism/include/prism/internal/bit.h +42 -0
  122. data/vendor/prism/include/prism/internal/buffer.h +94 -0
  123. data/vendor/prism/include/prism/internal/char.h +145 -0
  124. data/vendor/prism/include/prism/internal/comments.h +54 -0
  125. data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
  126. data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
  127. data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
  128. data/vendor/prism/include/prism/internal/integer.h +68 -0
  129. data/vendor/prism/include/prism/internal/isinf.h +16 -0
  130. data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
  131. data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
  132. data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
  133. data/vendor/prism/include/prism/internal/memchr.h +15 -0
  134. data/vendor/prism/include/prism/internal/node.h +42 -0
  135. data/vendor/prism/include/prism/internal/options.h +232 -0
  136. data/vendor/prism/include/prism/internal/parser.h +1015 -0
  137. data/vendor/prism/include/prism/internal/regexp.h +26 -0
  138. data/vendor/prism/include/prism/internal/serialize.h +39 -0
  139. data/vendor/prism/include/prism/internal/source.h +72 -0
  140. data/vendor/prism/include/prism/internal/static_literals.h +60 -0
  141. data/vendor/prism/include/prism/internal/stringy.h +30 -0
  142. data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
  143. data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
  144. data/vendor/prism/include/prism/internal/tokens.h +11 -0
  145. data/vendor/prism/include/prism/internal/xxh3.h +16 -0
  146. data/vendor/prism/include/prism/json.h +40 -0
  147. data/vendor/prism/include/prism/line_offset_list.h +69 -0
  148. data/vendor/prism/include/prism/magic_comments.h +53 -0
  149. data/vendor/prism/include/prism/node.h +59 -49
  150. data/vendor/prism/include/prism/node.hpp +272 -0
  151. data/vendor/prism/include/prism/node_type.hpp +38 -0
  152. data/vendor/prism/include/prism/options.h +154 -279
  153. data/vendor/prism/include/prism/options.hpp +43 -0
  154. data/vendor/prism/include/prism/parser.h +367 -870
  155. data/vendor/prism/include/prism/parser.hpp +274 -0
  156. data/vendor/prism/include/prism/prettyprint.h +14 -9
  157. data/vendor/prism/include/prism/serialize.h +123 -0
  158. data/vendor/prism/include/prism/source.h +163 -0
  159. data/vendor/prism/include/prism/stream.h +36 -0
  160. data/vendor/prism/include/prism/string_query.h +82 -0
  161. data/vendor/prism/include/prism/stringy.h +61 -0
  162. data/vendor/prism/include/prism/stringy.hpp +31 -0
  163. data/vendor/prism/include/prism/version.h +20 -3
  164. data/vendor/prism/include/prism.h +35 -320
  165. data/vendor/prism/include/prism.hpp +24 -0
  166. data/vendor/prism/src/arena.c +122 -0
  167. data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
  168. data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
  169. data/vendor/prism/src/comments.c +455 -0
  170. data/vendor/prism/src/constant_pool.c +406 -0
  171. data/vendor/prism/src/diagnostic.c +120 -68
  172. data/vendor/prism/src/encoding.c +8 -3
  173. data/vendor/prism/src/errors_format.c +519 -0
  174. data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
  175. data/vendor/prism/src/json.c +5733 -0
  176. data/vendor/prism/src/line_offset_list.c +100 -0
  177. data/vendor/prism/src/list.c +24 -0
  178. data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
  179. data/vendor/prism/src/node.c +3465 -7787
  180. data/vendor/prism/src/options.c +161 -54
  181. data/vendor/prism/src/parser.c +371 -0
  182. data/vendor/prism/src/prettyprint.c +421 -354
  183. data/vendor/prism/src/prism.c +8522 -7280
  184. data/vendor/prism/src/regexp.c +960 -45
  185. data/vendor/prism/src/serialize.c +2434 -2048
  186. data/vendor/prism/src/source.c +524 -0
  187. data/vendor/prism/src/static_literals.c +303 -360
  188. data/vendor/prism/src/string_query.c +180 -0
  189. data/vendor/prism/src/stringy.c +61 -0
  190. data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
  191. data/vendor/prism/src/strpbrk.c +447 -0
  192. data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
  193. data/vendor/prism/src/xxh3.c +292 -0
  194. data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
  195. data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
  196. data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
  197. data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
  198. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
  199. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
  200. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
  201. data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
  202. data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
  203. data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
  204. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
  205. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
  206. data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
  207. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
  208. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
  209. data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
  210. data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
  211. data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
  212. data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
  213. data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
  214. data/vendor/prism/templates/src/json.c.erb +130 -0
  215. data/vendor/prism/templates/src/node.c.erb +79 -236
  216. data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
  217. data/vendor/prism/templates/src/serialize.c.erb +369 -183
  218. data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
  219. data/vendor/prism/templates/template.rb +193 -91
  220. metadata +100 -42
  221. data/vendor/prism/include/prism/defines.h +0 -260
  222. data/vendor/prism/include/prism/pack.h +0 -163
  223. data/vendor/prism/include/prism/regexp.h +0 -43
  224. data/vendor/prism/include/prism/static_literals.h +0 -121
  225. data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
  226. data/vendor/prism/include/prism/util/pm_char.h +0 -204
  227. data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
  228. data/vendor/prism/include/prism/util/pm_integer.h +0 -130
  229. data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
  230. data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
  231. data/vendor/prism/include/prism/util/pm_string.h +0 -200
  232. data/vendor/prism/src/pack.c +0 -509
  233. data/vendor/prism/src/util/pm_constant_pool.c +0 -342
  234. data/vendor/prism/src/util/pm_list.c +0 -49
  235. data/vendor/prism/src/util/pm_newline_list.c +0 -125
  236. data/vendor/prism/src/util/pm_string.c +0 -381
  237. data/vendor/prism/src/util/pm_strpbrk.c +0 -206
  238. data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
  239. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
  240. data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
  241. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
  242. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
  243. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
  244. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
  245. data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
  246. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
  247. data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
@@ -38,7 +38,7 @@ void tag_helper_info_free(tag_helper_info_T** info);
38
38
  const tag_helper_handler_T* const* get_tag_helper_handlers(void);
39
39
  size_t get_tag_helper_handlers_count(void);
40
40
 
41
- char* extract_inline_block_content(pm_call_node_t* call_node, hb_allocator_T* allocator);
41
+ char* extract_inline_block_content(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator);
42
42
 
43
43
  struct AST_NODE_STRUCT;
44
44
  bool wrap_javascript_tag_body_visitor(const struct AST_NODE_STRUCT* node, void* data);
@@ -58,6 +58,7 @@ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_with_ruby_literal(
58
58
  AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_with_interpolated_value(
59
59
  const char* name_string,
60
60
  pm_interpolated_string_node_t* interpolated_node,
61
+ const uint8_t* source,
61
62
  position_T start_position,
62
63
  position_T end_position,
63
64
  hb_allocator_T* allocator
@@ -19,7 +19,7 @@ typedef struct {
19
19
  bool found;
20
20
  } tag_helper_search_data_T;
21
21
 
22
- bool search_tag_helper_node(const pm_node_t* node, void* data);
22
+ pm_visit_result_t search_tag_helper_node(const pm_node_t* node, void* data);
23
23
 
24
24
  position_T prism_location_to_position_with_offset(
25
25
  const pm_location_t* pm_location,
@@ -10,8 +10,9 @@
10
10
 
11
11
  typedef struct TAG_HELPER_SCOPE_STRUCT {
12
12
  hb_buffer_T buffer;
13
- pm_options_t options;
14
- pm_parser_t parser;
13
+ pm_arena_t* arena;
14
+ pm_options_t* options;
15
+ pm_parser_t* parser;
15
16
  pm_node_t* root;
16
17
  } tag_helper_scope_T;
17
18
 
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "../lib/hb_array.h"
5
5
  #include "../lib/hb_string.h"
6
+ #include "../parser/parser_options.h"
6
7
 
7
8
  #include <prism.h>
8
9
  #include <stdbool.h>
@@ -30,7 +31,8 @@ typedef enum {
30
31
  } control_type_t;
31
32
 
32
33
  typedef struct ANALYZED_RUBY_STRUCT {
33
- pm_parser_t parser;
34
+ pm_arena_t* arena;
35
+ pm_parser_t* parser;
34
36
  pm_node_t* root;
35
37
  bool valid;
36
38
  bool parsed;
@@ -58,7 +60,7 @@ typedef struct ANALYZED_RUBY_STRUCT {
58
60
  bool control_type_detected;
59
61
  } analyzed_ruby_T;
60
62
 
61
- analyzed_ruby_T* init_analyzed_ruby(hb_string_T source);
63
+ analyzed_ruby_T* init_analyzed_ruby(hb_string_T source, const parser_options_T* options);
62
64
  void free_analyzed_ruby(analyzed_ruby_T* analyzed);
63
65
  hb_string_T erb_keyword_from_analyzed_ruby(const analyzed_ruby_T* analyzed);
64
66
 
@@ -37,13 +37,13 @@ bool control_role_split_offset(const analyzed_ruby_T* analyzed, uint32_t* offset
37
37
 
38
38
  bool has_error_message(analyzed_ruby_T* anlayzed, const char* message);
39
39
 
40
- bool is_do_block(pm_location_t opening_location);
41
- bool is_brace_block(pm_location_t opening_location);
42
- bool is_closing_brace(pm_location_t location);
43
- bool has_valid_block_closing(pm_location_t opening_loc, pm_location_t closing_loc);
40
+ bool is_do_block(const uint8_t* source, pm_location_t opening_location);
41
+ bool is_brace_block(const uint8_t* source, pm_location_t opening_location);
42
+ bool is_closing_brace(const uint8_t* source, pm_location_t location);
43
+ bool has_valid_block_closing(const uint8_t* source, pm_location_t opening_loc, pm_location_t closing_loc);
44
44
 
45
- bool search_control_flow_nodes(const pm_node_t* node, void* data);
46
- bool search_unclosed_control_flows(const pm_node_t* node, void* data);
45
+ pm_visit_result_t search_control_flow_nodes(const pm_node_t* node, void* data);
46
+ pm_visit_result_t search_unclosed_control_flows(const pm_node_t* node, void* data);
47
47
  void search_unexpected_keyword_errors(analyzed_ruby_T* analyzed);
48
48
 
49
49
  void check_erb_node_for_missing_end(const AST_NODE_T* node, hb_allocator_T* allocator, const parser_options_T* options);
data/src/include/herb.h CHANGED
@@ -36,9 +36,10 @@ HERB_EXPORTED_FUNCTION const char* herb_version(void);
36
36
  HERB_EXPORTED_FUNCTION const char* herb_prism_version(void);
37
37
 
38
38
  typedef struct {
39
- pm_parser_t parser;
39
+ pm_arena_t* arena;
40
+ pm_parser_t* parser;
40
41
  pm_node_t* root;
41
- pm_options_t options;
42
+ pm_options_t* options;
42
43
  } herb_ruby_parse_result_T;
43
44
 
44
45
  HERB_EXPORTED_FUNCTION herb_ruby_parse_result_T* herb_parse_ruby(const char* source, size_t length);
@@ -10,6 +10,8 @@
10
10
  #include <stddef.h>
11
11
  #include <stdint.h>
12
12
 
13
+ #define HERB_PARSER_OPTIONS_STRING_CAPACITY 16
14
+
13
15
  typedef struct PARSER_OPTIONS_STRUCT {
14
16
  bool action_view_helpers;
15
17
  bool analyze;
@@ -24,6 +26,7 @@ typedef struct PARSER_OPTIONS_STRUCT {
24
26
  bool prism_nodes_deep;
25
27
  bool prism_program;
26
28
  bool render_nodes;
29
+ char ruby_version[HERB_PARSER_OPTIONS_STRING_CAPACITY];
27
30
  bool strict;
28
31
  bool strict_locals;
29
32
  uint32_t timeout_ms;
@@ -38,4 +41,6 @@ typedef struct PARSER_OPTIONS_STRUCT {
38
41
 
39
42
  extern const parser_options_T HERB_DEFAULT_PARSER_OPTIONS;
40
43
 
44
+ bool herb_ruby_version_supported(const char* value, size_t length);
45
+
41
46
  #endif
@@ -7,14 +7,16 @@
7
7
  #include <stdbool.h>
8
8
 
9
9
  typedef struct {
10
- pm_parser_t parser;
11
- pm_options_t pm_opts;
10
+ pm_arena_t* arena;
11
+ pm_parser_t* parser;
12
+ pm_options_t* pm_opts;
12
13
  pm_node_t* root;
13
14
  hb_buffer_T ruby_buf;
14
15
 
15
16
  bool has_structural;
16
- pm_parser_t structural_parser;
17
- pm_options_t structural_pm_opts;
17
+ pm_arena_t* structural_arena;
18
+ pm_parser_t* structural_parser;
19
+ pm_options_t* structural_pm_opts;
18
20
  pm_node_t* structural_root;
19
21
  hb_buffer_T structural_buf;
20
22
 
@@ -24,17 +26,15 @@ typedef struct {
24
26
  static inline void herb_prism_context_free(herb_prism_context_T* context) {
25
27
  if (!context) { return; }
26
28
 
27
- if (context->root) { pm_node_destroy(&context->parser, context->root); }
28
-
29
- pm_parser_free(&context->parser);
30
- pm_options_free(&context->pm_opts);
29
+ if (context->parser) { pm_parser_free(context->parser); }
30
+ if (context->arena) { pm_arena_free(context->arena); }
31
+ if (context->pm_opts) { pm_options_free(context->pm_opts); }
31
32
  hb_buffer_free(&context->ruby_buf);
32
33
 
33
34
  if (context->has_structural) {
34
- if (context->structural_root) { pm_node_destroy(&context->structural_parser, context->structural_root); }
35
-
36
- pm_parser_free(&context->structural_parser);
37
- pm_options_free(&context->structural_pm_opts);
35
+ if (context->structural_parser) { pm_parser_free(context->structural_parser); }
36
+ if (context->structural_arena) { pm_arena_free(context->structural_arena); }
37
+ if (context->structural_pm_opts) { pm_options_free(context->structural_pm_opts); }
38
38
 
39
39
  if (context->structural_buf.value) { hb_buffer_free(&context->structural_buf); }
40
40
  }
@@ -7,9 +7,39 @@
7
7
  #include "../lib/hb_allocator.h"
8
8
  #include "../location/location.h"
9
9
  #include "../location/position.h"
10
+ #include "../parser/parser_options.h"
10
11
 
11
12
  #include <prism.h>
12
13
 
14
+ static inline bool herb_prism_location_present(pm_location_t location) {
15
+ return location.length > 0;
16
+ }
17
+
18
+ static inline bool herb_prism_location_assigned(pm_location_t location) {
19
+ return location.start != 0 || location.length != 0;
20
+ }
21
+
22
+ static inline uint32_t herb_prism_location_end(pm_location_t location) {
23
+ return location.start + location.length;
24
+ }
25
+
26
+ static inline const uint8_t* herb_prism_location_start_pointer(const uint8_t* base, pm_location_t location) {
27
+ return base + location.start;
28
+ }
29
+
30
+ static inline const uint8_t* herb_prism_location_end_pointer(const uint8_t* base, pm_location_t location) {
31
+ return base + location.start + location.length;
32
+ }
33
+
34
+ void herb_prism_options_set_ruby_version(pm_options_t* options, const parser_options_T* parser_options);
35
+
36
+ pm_parser_t* herb_prism_parser_new(
37
+ pm_arena_t* arena,
38
+ const uint8_t* source,
39
+ size_t length,
40
+ const parser_options_T* parser_options
41
+ );
42
+
13
43
  hb_string_T pm_error_level_to_string(pm_error_level_t level);
14
44
 
15
45
  RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
@@ -0,0 +1,11 @@
1
+ // NOTE: This file is generated by the templates/template.rb script and should not
2
+ // be modified manually. See templates/src/include/prism_version.h.erb
3
+
4
+ #ifndef HERB_PRISM_VERSION_H
5
+ #define HERB_PRISM_VERSION_H
6
+
7
+ #include <prism/version.h>
8
+
9
+ #define HERB_PRISM_VERSION PRISM_VERSION "+4691667"
10
+
11
+ #endif
@@ -1,6 +1,6 @@
1
1
  #ifndef HERB_VERSION_H
2
2
  #define HERB_VERSION_H
3
3
 
4
- #define HERB_VERSION "0.11.1"
4
+ #define HERB_VERSION "0.11.2"
5
5
 
6
6
  #endif
@@ -195,8 +195,7 @@ void parser_append_literal_node_from_buffer(
195
195
 
196
196
  if (children != NULL) { hb_array_append(children, literal); }
197
197
 
198
- hb_buffer_free(buffer);
199
- hb_buffer_init(buffer, 128, parser->allocator);
198
+ hb_buffer_clear(buffer);
200
199
  }
201
200
 
202
201
  token_T* parser_advance(parser_T* parser) {
data/src/parser.c CHANGED
@@ -139,7 +139,7 @@ static AST_HTML_COMMENT_NODE_T* parser_parse_html_comment(parser_T* parser) {
139
139
  position_T start = parser->current_token->location.start;
140
140
 
141
141
  hb_buffer_T comment;
142
- hb_buffer_init(&comment, 512, parser->allocator);
142
+ hb_buffer_init(&comment, 64, parser->allocator);
143
143
 
144
144
  token_T* comment_end = NULL;
145
145
 
@@ -376,7 +376,7 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_arra
376
376
  position_T start = parser->current_token->location.start;
377
377
 
378
378
  hb_buffer_T content;
379
- hb_buffer_init(&content, 2048, parser->allocator);
379
+ hb_buffer_init(&content, 64, parser->allocator);
380
380
 
381
381
  while (token_is_none_of(
382
382
  parser,
@@ -553,7 +553,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value
553
553
  hb_array_T** errors
554
554
  ) {
555
555
  hb_buffer_T buffer;
556
- hb_buffer_init(&buffer, 512, parser->allocator);
556
+ hb_buffer_init(&buffer, 64, parser->allocator);
557
557
  token_T* opening_quote = parser_consume_expected(parser, TOKEN_QUOTE, errors);
558
558
  position_T start = parser->current_token->location.start;
559
559
 
@@ -816,7 +816,7 @@ static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser)
816
816
 
817
817
  if (has_equals) {
818
818
  hb_buffer_T equals_buffer;
819
- hb_buffer_init(&equals_buffer, 256, parser->allocator);
819
+ hb_buffer_init(&equals_buffer, 16, parser->allocator);
820
820
  position_T equals_start = { 0 };
821
821
  position_T equals_end = { 0 };
822
822
  uint32_t range_start = 0;
@@ -1640,13 +1640,12 @@ static void parser_append_foreign_content_from_buffer(
1640
1640
  ast_html_text_node_init(content, start, parser->current_token->location.start, NULL, parser->allocator)
1641
1641
  );
1642
1642
 
1643
- hb_buffer_free(buffer);
1644
- hb_buffer_init(buffer, 128, parser->allocator);
1643
+ hb_buffer_clear(buffer);
1645
1644
  }
1646
1645
 
1647
1646
  static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T** errors) {
1648
1647
  hb_buffer_T content;
1649
- hb_buffer_init(&content, 1024, parser->allocator);
1648
+ hb_buffer_init(&content, 64, parser->allocator);
1650
1649
  position_T start = parser->current_token->location.start;
1651
1650
  bool has_closing_tag = !hb_string_is_empty(parser->foreign_content_tag_name);
1652
1651
 
@@ -18,6 +18,7 @@ const parser_options_T HERB_DEFAULT_PARSER_OPTIONS = { .action_view_helpers = fa
18
18
  .prism_nodes_deep = false,
19
19
  .prism_program = false,
20
20
  .render_nodes = false,
21
+ .ruby_version = "4.0",
21
22
  .strict = true,
22
23
  .strict_locals = false,
23
24
  .timeout_ms = 1000,
@@ -7,9 +7,47 @@
7
7
  #include "../include/location/position.h"
8
8
 
9
9
  #include <prism.h>
10
+ #include <prism/internal/comments.h>
11
+ #include <prism/internal/parser.h>
10
12
  #include <stdlib.h>
11
13
  #include <string.h>
12
14
 
15
+ bool herb_ruby_version_supported(const char* value, size_t length) {
16
+ if (value == NULL || length == 0 || length >= HERB_PARSER_OPTIONS_STRING_CAPACITY) { return false; }
17
+
18
+ pm_options_t* options = pm_options_new();
19
+ bool supported = pm_options_version_set(options, value, length);
20
+ pm_options_free(options);
21
+
22
+ return supported;
23
+ }
24
+
25
+ void herb_prism_options_set_ruby_version(pm_options_t* options, const parser_options_T* parser_options) {
26
+ if (options == NULL || parser_options == NULL || parser_options->ruby_version[0] == '\0') { return; }
27
+
28
+ const char* version = parser_options->ruby_version;
29
+ pm_options_version_set(options, version, strnlen(version, HERB_PARSER_OPTIONS_STRING_CAPACITY));
30
+ }
31
+
32
+ pm_parser_t* herb_prism_parser_new(
33
+ pm_arena_t* arena,
34
+ const uint8_t* source,
35
+ size_t length,
36
+ const parser_options_T* parser_options
37
+ ) {
38
+ if (parser_options == NULL || parser_options->ruby_version[0] == '\0') {
39
+ return pm_parser_new(arena, source, length, NULL);
40
+ }
41
+
42
+ pm_options_t* options = pm_options_new();
43
+ herb_prism_options_set_ruby_version(options, parser_options);
44
+
45
+ pm_parser_t* parser = pm_parser_new(arena, source, length, options);
46
+ pm_options_free(options);
47
+
48
+ return parser;
49
+ }
50
+
13
51
  hb_string_T pm_error_level_to_string(pm_error_level_t level) {
14
52
  switch (level) {
15
53
  case PM_ERROR_LEVEL_SYNTAX: return hb_string("syntax");
@@ -25,16 +63,17 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
25
63
  pm_parser_t* parser,
26
64
  hb_allocator_T* allocator
27
65
  ) {
28
- size_t start_offset = (size_t) (error->location.start - parser->start);
29
- size_t end_offset = (size_t) (error->location.end - parser->start);
66
+ (void) parser;
30
67
 
31
- position_T start = position_from_source_with_offset(source, start_offset);
32
- position_T end = position_from_source_with_offset(source, end_offset);
68
+ pm_location_t location = pm_diagnostic_location(error);
69
+
70
+ position_T start = position_from_source_with_offset(source, location.start);
71
+ position_T end = position_from_source_with_offset(source, herb_prism_location_end(location));
33
72
 
34
73
  return ruby_parse_error_init(
35
- hb_string(error->message),
36
- hb_string(pm_diagnostic_id_human(error->diag_id)),
37
- pm_error_level_to_string(error->level),
74
+ hb_string(pm_diagnostic_message(error)),
75
+ hb_string(pm_diagnostic_type(error)),
76
+ pm_error_level_to_string(pm_diagnostic_error_level(error)),
38
77
  start,
39
78
  end,
40
79
  allocator
@@ -48,9 +87,9 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
48
87
  hb_allocator_T* allocator
49
88
  ) {
50
89
  return ruby_parse_error_init(
51
- hb_string(error->message),
52
- hb_string(pm_diagnostic_id_human(error->diag_id)),
53
- pm_error_level_to_string(error->level),
90
+ hb_string(pm_diagnostic_message(error)),
91
+ hb_string(pm_diagnostic_type(error)),
92
+ pm_error_level_to_string(pm_diagnostic_error_level(error)),
54
93
  start,
55
94
  end,
56
95
  allocator
@@ -62,55 +101,51 @@ typedef struct {
62
101
  bool found;
63
102
  } then_keyword_search_context_T;
64
103
 
65
- static bool has_pm_location(pm_location_t location) {
66
- return location.start != NULL && location.end != NULL && (location.end - location.start) > 0;
67
- }
68
-
69
- static bool search_then_keyword_location(const pm_node_t* node, void* data) {
104
+ static pm_visit_result_t search_then_keyword_location(const pm_node_t* node, void* data) {
70
105
  then_keyword_search_context_T* context = (then_keyword_search_context_T*) data;
71
106
 
72
- if (context->found) { return false; }
107
+ if (context->found) { return PM_VISIT_SKIP; }
73
108
 
74
109
  switch (node->type) {
75
110
  case PM_IF_NODE: {
76
111
  const pm_if_node_t* if_node = (const pm_if_node_t*) node;
77
112
 
78
- if (!has_pm_location(if_node->if_keyword_loc)) { break; }
113
+ if (!herb_prism_location_present(if_node->if_keyword_loc)) { break; }
79
114
 
80
- if (has_pm_location(if_node->then_keyword_loc)) {
115
+ if (herb_prism_location_present(if_node->then_keyword_loc)) {
81
116
  context->then_keyword_loc = if_node->then_keyword_loc;
82
117
  context->found = true;
83
- return false;
118
+ return PM_VISIT_SKIP;
84
119
  }
85
120
  break;
86
121
  }
87
122
 
88
123
  case PM_UNLESS_NODE: {
89
124
  const pm_unless_node_t* unless_node = (const pm_unless_node_t*) node;
90
- if (has_pm_location(unless_node->then_keyword_loc)) {
125
+ if (herb_prism_location_present(unless_node->then_keyword_loc)) {
91
126
  context->then_keyword_loc = unless_node->then_keyword_loc;
92
127
  context->found = true;
93
- return false;
128
+ return PM_VISIT_SKIP;
94
129
  }
95
130
  break;
96
131
  }
97
132
 
98
133
  case PM_WHEN_NODE: {
99
134
  const pm_when_node_t* when_node = (const pm_when_node_t*) node;
100
- if (has_pm_location(when_node->then_keyword_loc)) {
135
+ if (herb_prism_location_present(when_node->then_keyword_loc)) {
101
136
  context->then_keyword_loc = when_node->then_keyword_loc;
102
137
  context->found = true;
103
- return false;
138
+ return PM_VISIT_SKIP;
104
139
  }
105
140
  break;
106
141
  }
107
142
 
108
143
  case PM_IN_NODE: {
109
144
  const pm_in_node_t* in_node = (const pm_in_node_t*) node;
110
- if (has_pm_location(in_node->then_loc)) {
111
- context->then_keyword_loc = in_node->then_loc;
145
+ if (herb_prism_location_present(in_node->then_keyword_loc)) {
146
+ context->then_keyword_loc = in_node->then_keyword_loc;
112
147
  context->found = true;
113
- return false;
148
+ return PM_VISIT_SKIP;
114
149
  }
115
150
  break;
116
151
  }
@@ -120,23 +155,20 @@ static bool search_then_keyword_location(const pm_node_t* node, void* data) {
120
155
 
121
156
  pm_visit_child_nodes(node, search_then_keyword_location, context);
122
157
 
123
- return false;
158
+ return PM_VISIT_SKIP;
124
159
  }
125
160
 
126
161
  location_T* get_then_keyword_location(analyzed_ruby_T* analyzed, const char* source, hb_allocator_T* allocator) {
127
162
  if (analyzed == NULL || analyzed->root == NULL || source == NULL) { return NULL; }
128
163
 
129
- then_keyword_search_context_T context = { .then_keyword_loc = { .start = NULL, .end = NULL }, .found = false };
164
+ then_keyword_search_context_T context = { .then_keyword_loc = { .start = 0, .length = 0 }, .found = false };
130
165
 
131
166
  pm_visit_child_nodes(analyzed->root, search_then_keyword_location, &context);
132
167
 
133
168
  if (!context.found) { return NULL; }
134
169
 
135
- size_t start_offset = (size_t) (context.then_keyword_loc.start - analyzed->parser.start);
136
- size_t end_offset = (size_t) (context.then_keyword_loc.end - analyzed->parser.start);
137
-
138
- position_T start_position = position_from_source_with_offset(source, start_offset);
139
- position_T end_position = position_from_source_with_offset(source, end_offset);
170
+ position_T start_position = position_from_source_with_offset(source, context.then_keyword_loc.start);
171
+ position_T end_position = position_from_source_with_offset(source, herb_prism_location_end(context.then_keyword_loc));
140
172
 
141
173
  return location_create(start_position, end_position, allocator);
142
174
  }
@@ -150,25 +182,26 @@ static location_T* parse_wrapped_and_find_then_keyword(
150
182
  size_t adjustment_amount,
151
183
  hb_allocator_T* allocator
152
184
  ) {
153
- pm_parser_t parser;
154
- pm_parser_init(&parser, (const uint8_t*) hb_buffer_value(buffer), hb_buffer_length(buffer), NULL);
155
- pm_node_t* root = pm_parse(&parser);
185
+ pm_arena_t* arena = pm_arena_new();
186
+ pm_parser_t* parser = pm_parser_new(arena, (const uint8_t*) hb_buffer_value(buffer), hb_buffer_length(buffer), NULL);
187
+ pm_node_t* root = pm_parse(parser);
156
188
 
157
189
  if (root == NULL) {
158
- pm_parser_free(&parser);
190
+ pm_parser_free(parser);
191
+ pm_arena_free(arena);
159
192
 
160
193
  return NULL;
161
194
  }
162
195
 
163
- then_keyword_search_context_T context = { .then_keyword_loc = { .start = NULL, .end = NULL }, .found = false };
196
+ then_keyword_search_context_T context = { .then_keyword_loc = { .start = 0, .length = 0 }, .found = false };
164
197
 
165
198
  pm_visit_child_nodes(root, search_then_keyword_location, &context);
166
199
 
167
200
  location_T* location = NULL;
168
201
 
169
202
  if (context.found) {
170
- size_t start_offset = (size_t) (context.then_keyword_loc.start - parser.start);
171
- size_t end_offset = (size_t) (context.then_keyword_loc.end - parser.start);
203
+ size_t start_offset = context.then_keyword_loc.start;
204
+ size_t end_offset = herb_prism_location_end(context.then_keyword_loc);
172
205
 
173
206
  if (start_offset >= prefix_length && end_offset >= prefix_length) {
174
207
  start_offset -= prefix_length;
@@ -188,8 +221,8 @@ static location_T* parse_wrapped_and_find_then_keyword(
188
221
  }
189
222
  }
190
223
 
191
- pm_node_destroy(&parser, root);
192
- pm_parser_free(&parser);
224
+ pm_parser_free(parser);
225
+ pm_arena_free(arena);
193
226
 
194
227
  return location;
195
228
  }
@@ -245,7 +278,7 @@ location_T* get_then_keyword_location_elsif_wrapped(const char* source, hb_alloc
245
278
  return location;
246
279
  }
247
280
 
248
- static size_t newline_index_for_offset(const pm_newline_list_t* newlines, size_t offset) {
281
+ static size_t newline_index_for_offset(const pm_line_offset_list_t* newlines, size_t offset) {
249
282
  size_t low = 0;
250
283
  size_t high = newlines->size;
251
284
 
@@ -267,12 +300,12 @@ void herb_prism_node_serialize(herb_prism_node_T prism_node, pm_buffer_t* buffer
267
300
 
268
301
  pm_parser_t* parser = prism_node.parser;
269
302
 
270
- if (prism_node.source_end == 0 || parser->newline_list.size == 0) {
303
+ if (prism_node.source_end == 0 || parser->line_offsets.size == 0) {
271
304
  pm_serialize(parser, prism_node.node, buffer);
272
305
  return;
273
306
  }
274
307
 
275
- const pm_newline_list_t* newlines = &parser->newline_list;
308
+ const pm_line_offset_list_t* newlines = &parser->line_offsets;
276
309
  size_t first_line = newline_index_for_offset(newlines, prism_node.source_start);
277
310
  size_t last_line = newline_index_for_offset(newlines, prism_node.source_end);
278
311
  size_t line_count = last_line - first_line + 1;
@@ -281,21 +314,22 @@ void herb_prism_node_serialize(herb_prism_node_T prism_node, pm_buffer_t* buffer
281
314
 
282
315
  pm_parser_t view = *parser;
283
316
 
284
- view.newline_list.offsets = newlines->offsets + first_line;
285
- view.newline_list.size = line_count;
286
- view.newline_list.capacity = line_count;
317
+ view.line_offsets.offsets = newlines->offsets + first_line;
318
+ view.line_offsets.size = line_count;
319
+ view.line_offsets.capacity = line_count;
287
320
  view.start_line = parser->start_line + (int32_t) first_line;
288
321
 
289
322
  memset(&view.magic_comment_list, 0, sizeof(pm_list_t));
290
323
  memset(&view.error_list, 0, sizeof(pm_list_t));
291
324
  memset(&view.warning_list, 0, sizeof(pm_list_t));
292
325
  memset(&view.comment_list, 0, sizeof(pm_list_t));
326
+ memset(&view.comment_attachments, 0, sizeof(view.comment_attachments));
293
327
 
294
328
  size_t comment_count = 0;
295
329
 
296
330
  for (pm_list_node_t* entry = parser->comment_list.head; entry; entry = entry->next) {
297
331
  pm_comment_t* comment = (pm_comment_t*) entry;
298
- size_t start = (size_t) (comment->location.start - parser->start);
332
+ size_t start = comment->location.start;
299
333
 
300
334
  if (start >= prism_node.source_start && start < prism_node.source_end) { comment_count++; }
301
335
  }
@@ -314,7 +348,7 @@ void herb_prism_node_serialize(herb_prism_node_T prism_node, pm_buffer_t* buffer
314
348
 
315
349
  for (pm_list_node_t* entry = parser->comment_list.head; entry; entry = entry->next) {
316
350
  pm_comment_t* comment = (pm_comment_t*) entry;
317
- size_t start = (size_t) (comment->location.start - parser->start);
351
+ size_t start = comment->location.start;
318
352
 
319
353
  if (start < prism_node.source_start || start >= prism_node.source_end) { continue; }
320
354