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
@@ -1,4 +1,5 @@
1
1
  #include <prism.h>
2
+ #include <prism/internal/diagnostic.h>
2
3
  #include <stdbool.h>
3
4
  #include <string.h>
4
5
 
@@ -94,22 +95,21 @@ bool has_inline_case_condition(analyzed_ruby_T* analyzed) {
94
95
  }
95
96
 
96
97
  typedef struct {
97
- const uint8_t* source_start;
98
98
  uint32_t offset;
99
99
  bool found;
100
100
  } inline_condition_offset_T;
101
101
 
102
- static bool search_inline_condition_offset(const pm_node_t* node, void* data) {
102
+ static pm_visit_result_t search_inline_condition_offset(const pm_node_t* node, void* data) {
103
103
  inline_condition_offset_T* context = (inline_condition_offset_T*) data;
104
104
 
105
105
  uint32_t keyword_offset = UINT32_MAX;
106
106
 
107
107
  if (node->type == PM_WHEN_NODE) {
108
- keyword_offset = (uint32_t) (((const pm_when_node_t*) node)->keyword_loc.start - context->source_start);
108
+ keyword_offset = ((const pm_when_node_t*) node)->when_keyword_loc.start;
109
109
  } else if (node->type == PM_IN_NODE) {
110
- keyword_offset = (uint32_t) (((const pm_in_node_t*) node)->in_loc.start - context->source_start);
110
+ keyword_offset = ((const pm_in_node_t*) node)->in_keyword_loc.start;
111
111
  } else if (node->type == PM_MATCH_PREDICATE_NODE) {
112
- keyword_offset = (uint32_t) (((const pm_match_predicate_node_t*) node)->operator_loc.start - context->source_start);
112
+ keyword_offset = ((const pm_match_predicate_node_t*) node)->keyword_loc.start;
113
113
  }
114
114
 
115
115
  if (keyword_offset != UINT32_MAX && (!context->found || keyword_offset < context->offset)) {
@@ -119,7 +119,7 @@ static bool search_inline_condition_offset(const pm_node_t* node, void* data) {
119
119
 
120
120
  pm_visit_child_nodes(node, search_inline_condition_offset, context);
121
121
 
122
- return false;
122
+ return PM_VISIT_SKIP;
123
123
  }
124
124
 
125
125
  static hb_string_T control_continuation_keywords[] = HB_STRING_LIST("else", "elsif", "when", "in", "rescue", "ensure");
@@ -157,19 +157,18 @@ bool control_role_split_offset(const analyzed_ruby_T* analyzed, uint32_t* offset
157
157
  uint32_t second = UINT32_MAX;
158
158
  bool first_continues = false;
159
159
 
160
- for (const pm_diagnostic_t* diagnostic = (const pm_diagnostic_t*) analyzed->parser.error_list.head;
161
- diagnostic != NULL;
162
- diagnostic = (const pm_diagnostic_t*) diagnostic->node.next) {
160
+ const uint8_t* source = pm_parser_start(analyzed->parser);
161
+
162
+ for (const pm_diagnostic_t* diagnostic = pm_parser_errors_first(analyzed->parser); diagnostic != NULL;
163
+ diagnostic = pm_diagnostic_next(diagnostic)) {
163
164
  if (diagnostic->diag_id != PM_ERR_UNEXPECTED_TOKEN_IGNORE) { continue; }
164
165
 
165
- hb_string_T keyword = hb_string_from_data(
166
- (const char*) diagnostic->location.start,
167
- (size_t) (diagnostic->location.end - diagnostic->location.start)
168
- );
166
+ hb_string_T keyword =
167
+ hb_string_from_data((const char*) (source + diagnostic->location.start), diagnostic->location.length);
169
168
 
170
169
  if (!is_control_role_keyword(keyword)) { continue; }
171
170
 
172
- uint32_t start = (uint32_t) (diagnostic->location.start - analyzed->parser.start);
171
+ uint32_t start = diagnostic->location.start;
173
172
 
174
173
  if (start < first) {
175
174
  second = first;
@@ -203,7 +202,6 @@ bool inline_condition_keyword_offset(const analyzed_ruby_T* analyzed, uint32_t*
203
202
  if (!analyzed || !analyzed->root || !offset) { return false; }
204
203
 
205
204
  inline_condition_offset_T context = {
206
- .source_start = analyzed->parser.start,
207
205
  .offset = UINT32_MAX,
208
206
  .found = false,
209
207
  };
@@ -218,89 +216,76 @@ bool inline_condition_keyword_offset(const analyzed_ruby_T* analyzed, uint32_t*
218
216
  }
219
217
 
220
218
  bool has_error_message(analyzed_ruby_T* analyzed, const char* message) {
221
- for (const pm_diagnostic_t* error = (const pm_diagnostic_t*) analyzed->parser.error_list.head; error != NULL;
222
- error = (const pm_diagnostic_t*) error->node.next) {
223
- if (string_equals(error->message, message)) { return true; }
219
+ for (const pm_diagnostic_t* error = pm_parser_errors_first(analyzed->parser); error != NULL;
220
+ error = pm_diagnostic_next(error)) {
221
+ if (string_equals(pm_diagnostic_message(error), message)) { return true; }
224
222
  }
225
223
 
226
224
  return false;
227
225
  }
228
226
 
229
- bool is_do_block(pm_location_t opening_location) {
230
- size_t length = opening_location.end - opening_location.start;
231
-
232
- return length == 2 && opening_location.start[0] == 'd' && opening_location.start[1] == 'o';
227
+ static bool location_matches(const uint8_t* source, pm_location_t location, const char* text, size_t length) {
228
+ return location.length == length && memcmp(source + location.start, text, length) == 0;
233
229
  }
234
230
 
235
- bool is_brace_block(pm_location_t opening_location) {
236
- size_t length = opening_location.end - opening_location.start;
237
-
238
- return length == 1 && opening_location.start[0] == '{';
231
+ bool is_do_block(const uint8_t* source, pm_location_t opening_location) {
232
+ return location_matches(source, opening_location, "do", 2);
239
233
  }
240
234
 
241
- static bool has_location(pm_location_t location) {
242
- return location.start != NULL && location.end != NULL && (location.end - location.start) > 0;
235
+ bool is_brace_block(const uint8_t* source, pm_location_t opening_location) {
236
+ return location_matches(source, opening_location, "{", 1);
243
237
  }
244
238
 
245
- static bool is_end_keyword(pm_location_t location) {
246
- if (location.start == NULL || location.end == NULL) { return false; }
247
-
248
- size_t length = location.end - location.start;
249
-
250
- return length == 3 && location.start[0] == 'e' && location.start[1] == 'n' && location.start[2] == 'd';
239
+ static bool is_end_keyword(const uint8_t* source, pm_location_t location) {
240
+ return location_matches(source, location, "end", 3);
251
241
  }
252
242
 
253
- bool is_closing_brace(pm_location_t location) {
254
- if (location.start == NULL || location.end == NULL) { return false; }
255
-
256
- size_t length = location.end - location.start;
257
-
258
- return length == 1 && location.start[0] == '}';
243
+ bool is_closing_brace(const uint8_t* source, pm_location_t location) {
244
+ return location_matches(source, location, "}", 1);
259
245
  }
260
246
 
261
- bool has_valid_block_closing(pm_location_t opening_loc, pm_location_t closing_loc) {
262
- if (is_do_block(opening_loc)) {
263
- return is_end_keyword(closing_loc);
264
- } else if (is_brace_block(opening_loc)) {
265
- return is_closing_brace(closing_loc);
247
+ bool has_valid_block_closing(const uint8_t* source, pm_location_t opening_loc, pm_location_t closing_loc) {
248
+ if (is_do_block(source, opening_loc)) {
249
+ return is_end_keyword(source, closing_loc);
250
+ } else if (is_brace_block(source, opening_loc)) {
251
+ return is_closing_brace(source, closing_loc);
266
252
  }
267
253
 
268
254
  return false;
269
255
  }
270
256
 
271
- static bool has_keyword_location(pm_location_t location) {
272
- return location.start != NULL && location.end != NULL;
273
- }
274
-
275
- static bool is_unclosed_block(pm_location_t opening_loc, pm_location_t closing_loc) {
276
- bool has_opening = is_do_block(opening_loc) || is_brace_block(opening_loc);
257
+ static bool is_unclosed_block(const uint8_t* source, pm_location_t opening_loc, pm_location_t closing_loc) {
258
+ bool has_opening = is_do_block(source, opening_loc) || is_brace_block(source, opening_loc);
277
259
 
278
- return has_opening && !has_valid_block_closing(opening_loc, closing_loc);
260
+ return has_opening && !has_valid_block_closing(source, opening_loc, closing_loc);
279
261
  }
280
262
 
281
- bool search_control_flow_nodes(const pm_node_t* node, void* data) {
263
+ pm_visit_result_t search_control_flow_nodes(const pm_node_t* node, void* data) {
282
264
  analyzed_ruby_T* analyzed = (analyzed_ruby_T*) data;
265
+ const uint8_t* source = pm_parser_start(analyzed->parser);
283
266
 
284
267
  switch (node->type) {
285
268
  case PM_IF_NODE: {
286
269
  const pm_if_node_t* if_node = (const pm_if_node_t*) node;
287
270
 
288
- if (has_keyword_location(if_node->if_keyword_loc) && has_keyword_location(if_node->end_keyword_loc)) {
271
+ if (herb_prism_location_assigned(if_node->if_keyword_loc)
272
+ && herb_prism_location_assigned(if_node->end_keyword_loc)) {
289
273
  analyzed->if_node_count++;
290
274
  }
291
275
 
292
- if (has_keyword_location(if_node->then_keyword_loc)) { analyzed->then_keyword_count++; }
276
+ if (herb_prism_location_assigned(if_node->then_keyword_loc)) { analyzed->then_keyword_count++; }
293
277
  break;
294
278
  }
295
279
 
296
280
  case PM_UNLESS_NODE: {
297
281
  const pm_unless_node_t* unless_node = (const pm_unless_node_t*) node;
298
282
 
299
- if (has_keyword_location(unless_node->keyword_loc) && has_keyword_location(unless_node->end_keyword_loc)) {
283
+ if (herb_prism_location_assigned(unless_node->unless_keyword_loc)
284
+ && herb_prism_location_assigned(unless_node->end_keyword_loc)) {
300
285
  analyzed->unless_node_count++;
301
286
  }
302
287
 
303
- if (has_keyword_location(unless_node->then_keyword_loc)) { analyzed->then_keyword_count++; }
288
+ if (herb_prism_location_assigned(unless_node->then_keyword_loc)) { analyzed->then_keyword_count++; }
304
289
  break;
305
290
  }
306
291
 
@@ -309,21 +294,23 @@ bool search_control_flow_nodes(const pm_node_t* node, void* data) {
309
294
 
310
295
  analyzed->when_node_count++;
311
296
 
312
- if (has_keyword_location(when_node->then_keyword_loc)) { analyzed->then_keyword_count++; }
297
+ if (herb_prism_location_assigned(when_node->then_keyword_loc)) { analyzed->then_keyword_count++; }
313
298
  break;
314
299
  }
315
300
 
316
301
  case PM_BLOCK_NODE: {
317
302
  const pm_block_node_t* block_node = (const pm_block_node_t*) node;
318
303
 
319
- if (is_unclosed_block(block_node->opening_loc, block_node->closing_loc)) { analyzed->block_node_count++; }
304
+ if (is_unclosed_block(source, block_node->opening_loc, block_node->closing_loc)) { analyzed->block_node_count++; }
320
305
  break;
321
306
  }
322
307
 
323
308
  case PM_LAMBDA_NODE: {
324
309
  const pm_lambda_node_t* lambda_node = (const pm_lambda_node_t*) node;
325
310
 
326
- if (is_unclosed_block(lambda_node->opening_loc, lambda_node->closing_loc)) { analyzed->block_node_count++; }
311
+ if (is_unclosed_block(source, lambda_node->opening_loc, lambda_node->closing_loc)) {
312
+ analyzed->block_node_count++;
313
+ }
327
314
  break;
328
315
  }
329
316
 
@@ -351,7 +338,7 @@ bool search_control_flow_nodes(const pm_node_t* node, void* data) {
351
338
 
352
339
  pm_visit_child_nodes(node, search_control_flow_nodes, analyzed);
353
340
 
354
- return false;
341
+ return PM_VISIT_SKIP;
355
342
  }
356
343
 
357
344
  void search_unexpected_keyword_errors(analyzed_ruby_T* analyzed) {
@@ -365,9 +352,9 @@ void search_unexpected_keyword_errors(analyzed_ruby_T* analyzed) {
365
352
  bool unexpected_rescue = false;
366
353
  bool unexpected_ensure = false;
367
354
 
368
- for (const pm_diagnostic_t* error = (const pm_diagnostic_t*) analyzed->parser.error_list.head; error != NULL;
369
- error = (const pm_diagnostic_t*) error->node.next) {
370
- const char* message = error->message;
355
+ for (const pm_diagnostic_t* error = pm_parser_errors_first(analyzed->parser); error != NULL;
356
+ error = pm_diagnostic_next(error)) {
357
+ const char* message = pm_diagnostic_message(error);
371
358
 
372
359
  if (string_equals(message, "unexpected 'elsif', ignoring it")) {
373
360
  unexpected_elsif = true;
@@ -406,16 +393,17 @@ static bool is_postfix_conditional(const pm_statements_node_t* statements, pm_lo
406
393
  return statements->base.location.start < keyword_location.start;
407
394
  }
408
395
 
409
- bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
396
+ pm_visit_result_t search_unclosed_control_flows(const pm_node_t* node, void* data) {
410
397
  analyzed_ruby_T* analyzed = (analyzed_ruby_T*) data;
398
+ const uint8_t* source = pm_parser_start(analyzed->parser);
411
399
 
412
- if (analyzed->unclosed_control_flow_count >= 2) { return false; }
400
+ if (analyzed->unclosed_control_flow_count >= 2) { return PM_VISIT_SKIP; }
413
401
 
414
402
  switch (node->type) {
415
403
  case PM_IF_NODE: {
416
404
  const pm_if_node_t* if_node = (const pm_if_node_t*) node;
417
405
 
418
- if (has_location(if_node->if_keyword_loc) && !is_end_keyword(if_node->end_keyword_loc)) {
406
+ if (herb_prism_location_present(if_node->if_keyword_loc) && !is_end_keyword(source, if_node->end_keyword_loc)) {
419
407
  if (!is_postfix_conditional(if_node->statements, if_node->if_keyword_loc)) {
420
408
  analyzed->unclosed_control_flow_count++;
421
409
  }
@@ -427,8 +415,9 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
427
415
  case PM_UNLESS_NODE: {
428
416
  const pm_unless_node_t* unless_node = (const pm_unless_node_t*) node;
429
417
 
430
- if (has_location(unless_node->keyword_loc) && !is_end_keyword(unless_node->end_keyword_loc)) {
431
- if (!is_postfix_conditional(unless_node->statements, unless_node->keyword_loc)) {
418
+ if (herb_prism_location_present(unless_node->unless_keyword_loc)
419
+ && !is_end_keyword(source, unless_node->end_keyword_loc)) {
420
+ if (!is_postfix_conditional(unless_node->statements, unless_node->unless_keyword_loc)) {
432
421
  analyzed->unclosed_control_flow_count++;
433
422
  }
434
423
  }
@@ -439,7 +428,8 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
439
428
  case PM_CASE_NODE: {
440
429
  const pm_case_node_t* case_node = (const pm_case_node_t*) node;
441
430
 
442
- if (has_location(case_node->case_keyword_loc) && !is_end_keyword(case_node->end_keyword_loc)) {
431
+ if (herb_prism_location_present(case_node->case_keyword_loc)
432
+ && !is_end_keyword(source, case_node->end_keyword_loc)) {
443
433
  analyzed->unclosed_control_flow_count++;
444
434
  }
445
435
 
@@ -449,7 +439,8 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
449
439
  case PM_CASE_MATCH_NODE: {
450
440
  const pm_case_match_node_t* case_match_node = (const pm_case_match_node_t*) node;
451
441
 
452
- if (has_location(case_match_node->case_keyword_loc) && !is_end_keyword(case_match_node->end_keyword_loc)) {
442
+ if (herb_prism_location_present(case_match_node->case_keyword_loc)
443
+ && !is_end_keyword(source, case_match_node->end_keyword_loc)) {
453
444
  analyzed->unclosed_control_flow_count++;
454
445
  }
455
446
 
@@ -459,7 +450,8 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
459
450
  case PM_WHILE_NODE: {
460
451
  const pm_while_node_t* while_node = (const pm_while_node_t*) node;
461
452
 
462
- if (has_location(while_node->keyword_loc) && !is_end_keyword(while_node->closing_loc)) {
453
+ if (herb_prism_location_present(while_node->while_keyword_loc)
454
+ && !is_end_keyword(source, while_node->end_keyword_loc)) {
463
455
  analyzed->unclosed_control_flow_count++;
464
456
  }
465
457
 
@@ -469,7 +461,8 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
469
461
  case PM_UNTIL_NODE: {
470
462
  const pm_until_node_t* until_node = (const pm_until_node_t*) node;
471
463
 
472
- if (has_location(until_node->keyword_loc) && !is_end_keyword(until_node->closing_loc)) {
464
+ if (herb_prism_location_present(until_node->until_keyword_loc)
465
+ && !is_end_keyword(source, until_node->end_keyword_loc)) {
473
466
  analyzed->unclosed_control_flow_count++;
474
467
  }
475
468
 
@@ -479,7 +472,8 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
479
472
  case PM_FOR_NODE: {
480
473
  const pm_for_node_t* for_node = (const pm_for_node_t*) node;
481
474
 
482
- if (has_location(for_node->for_keyword_loc) && !is_end_keyword(for_node->end_keyword_loc)) {
475
+ if (herb_prism_location_present(for_node->for_keyword_loc)
476
+ && !is_end_keyword(source, for_node->end_keyword_loc)) {
483
477
  analyzed->unclosed_control_flow_count++;
484
478
  }
485
479
 
@@ -489,7 +483,8 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
489
483
  case PM_BEGIN_NODE: {
490
484
  const pm_begin_node_t* begin_node = (const pm_begin_node_t*) node;
491
485
 
492
- if (has_location(begin_node->begin_keyword_loc) && !is_end_keyword(begin_node->end_keyword_loc)) {
486
+ if (herb_prism_location_present(begin_node->begin_keyword_loc)
487
+ && !is_end_keyword(source, begin_node->end_keyword_loc)) {
493
488
  analyzed->unclosed_control_flow_count++;
494
489
  }
495
490
 
@@ -498,9 +493,10 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
498
493
 
499
494
  case PM_BLOCK_NODE: {
500
495
  const pm_block_node_t* block_node = (const pm_block_node_t*) node;
501
- bool has_opening = is_do_block(block_node->opening_loc) || is_brace_block(block_node->opening_loc);
496
+ bool has_opening =
497
+ is_do_block(source, block_node->opening_loc) || is_brace_block(source, block_node->opening_loc);
502
498
 
503
- if (has_opening && !has_valid_block_closing(block_node->opening_loc, block_node->closing_loc)) {
499
+ if (has_opening && !has_valid_block_closing(source, block_node->opening_loc, block_node->closing_loc)) {
504
500
  analyzed->unclosed_control_flow_count++;
505
501
  }
506
502
 
@@ -509,9 +505,10 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
509
505
 
510
506
  case PM_LAMBDA_NODE: {
511
507
  const pm_lambda_node_t* lambda_node = (const pm_lambda_node_t*) node;
512
- bool has_opening = is_do_block(lambda_node->opening_loc) || is_brace_block(lambda_node->opening_loc);
508
+ bool has_opening =
509
+ is_do_block(source, lambda_node->opening_loc) || is_brace_block(source, lambda_node->opening_loc);
513
510
 
514
- if (has_opening && !has_valid_block_closing(lambda_node->opening_loc, lambda_node->closing_loc)) {
511
+ if (has_opening && !has_valid_block_closing(source, lambda_node->opening_loc, lambda_node->closing_loc)) {
515
512
  analyzed->unclosed_control_flow_count++;
516
513
  }
517
514
 
@@ -523,7 +520,7 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
523
520
 
524
521
  pm_visit_child_nodes(node, search_unclosed_control_flows, analyzed);
525
522
 
526
- return false;
523
+ return PM_VISIT_SKIP;
527
524
  }
528
525
 
529
526
  static pm_block_node_t* find_first_block_node(pm_node_t* node) {
@@ -552,28 +549,21 @@ static pm_block_node_t* find_first_block_node(pm_node_t* node) {
552
549
  return NULL;
553
550
  }
554
551
 
555
- static position_T prism_to_source_position(
556
- const uint8_t* prism_pointer,
557
- const uint8_t* prism_source_start,
558
- size_t source_base_offset,
559
- const char* source
560
- ) {
561
- if (!source || !prism_source_start) { return (position_T) { .line = 1, .column = 0 }; }
552
+ static position_T prism_to_source_position(uint32_t prism_offset, size_t source_base_offset, const char* source) {
553
+ if (!source) { return (position_T) { .line = 1, .column = 0 }; }
562
554
 
563
- size_t prism_offset = (size_t) (prism_pointer - prism_source_start);
564
555
  return byte_offset_to_position(source, source_base_offset + prism_offset);
565
556
  }
566
557
 
567
558
  static token_T* create_parameter_name_token(
568
559
  pm_location_t location,
569
560
  const char* name,
570
- const uint8_t* prism_source_start,
571
561
  size_t source_base_offset,
572
562
  const char* source,
573
563
  hb_allocator_T* allocator
574
564
  ) {
575
- position_T start = prism_to_source_position(location.start, prism_source_start, source_base_offset, source);
576
- position_T end = prism_to_source_position(location.end, prism_source_start, source_base_offset, source);
565
+ position_T start = prism_to_source_position(location.start, source_base_offset, source);
566
+ position_T end = prism_to_source_position(herb_prism_location_end(location), source_base_offset, source);
577
567
 
578
568
  return create_synthetic_token(allocator, name, TOKEN_IDENTIFIER, start, end);
579
569
  }
@@ -639,20 +629,21 @@ static void append_multi_target_parameters(
639
629
 
640
630
  if (splat->expression && splat->expression->type == PM_REQUIRED_PARAMETER_NODE) {
641
631
  pm_required_parameter_node_t* required = (pm_required_parameter_node_t*) splat->expression;
642
- pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, required->name);
632
+ const pm_constant_t* constant = pm_parser_constant(parser, required->name);
643
633
 
644
634
  if (constant) {
645
- char* name = hb_allocator_strndup(allocator, (const char*) constant->start, constant->length);
635
+ char* name =
636
+ hb_allocator_strndup(allocator, (const char*) pm_constant_start(constant), pm_constant_length(constant));
646
637
  pm_node_t* node = splat->expression;
647
638
 
648
639
  append_parameter(
649
640
  result,
650
- create_parameter_name_token(node->location, name, prism_source_start, source_base_offset, source, allocator),
641
+ create_parameter_name_token(node->location, name, source_base_offset, source, allocator),
651
642
  NULL,
652
643
  "rest",
653
644
  false,
654
- prism_to_source_position(node->location.start, prism_source_start, source_base_offset, source),
655
- prism_to_source_position(node->location.end, prism_source_start, source_base_offset, source),
645
+ prism_to_source_position(node->location.start, source_base_offset, source),
646
+ prism_to_source_position(herb_prism_location_end(node->location), source_base_offset, source),
656
647
  allocator
657
648
  );
658
649
 
@@ -700,19 +691,19 @@ static void append_required_positional(
700
691
  if (node->type != PM_REQUIRED_PARAMETER_NODE) { return; }
701
692
 
702
693
  pm_required_parameter_node_t* required = (pm_required_parameter_node_t*) node;
703
- pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, required->name);
694
+ const pm_constant_t* constant = pm_parser_constant(parser, required->name);
704
695
  if (!constant) { return; }
705
696
 
706
- char* name = hb_allocator_strndup(allocator, (const char*) constant->start, constant->length);
697
+ char* name = hb_allocator_strndup(allocator, (const char*) pm_constant_start(constant), pm_constant_length(constant));
707
698
 
708
699
  append_parameter(
709
700
  result,
710
- create_parameter_name_token(node->location, name, prism_source_start, source_base_offset, source, allocator),
701
+ create_parameter_name_token(node->location, name, source_base_offset, source, allocator),
711
702
  NULL,
712
703
  "positional",
713
704
  true,
714
- prism_to_source_position(node->location.start, prism_source_start, source_base_offset, source),
715
- prism_to_source_position(node->location.end, prism_source_start, source_base_offset, source),
705
+ prism_to_source_position(node->location.start, source_base_offset, source),
706
+ prism_to_source_position(herb_prism_location_end(node->location), source_base_offset, source),
716
707
  allocator
717
708
  );
718
709
 
@@ -755,21 +746,25 @@ hb_array_T* extract_parameters_from_prism(
755
746
  if (node->type != PM_OPTIONAL_PARAMETER_NODE) { continue; }
756
747
 
757
748
  pm_optional_parameter_node_t* optional = (pm_optional_parameter_node_t*) node;
758
- size_t name_length = (size_t) (optional->name_loc.end - optional->name_loc.start);
759
- char* name = hb_allocator_strndup(allocator, (const char*) optional->name_loc.start, name_length);
749
+ size_t name_length = optional->name_loc.length;
750
+ char* name =
751
+ hb_allocator_strndup(allocator, (const char*) (prism_source_start + optional->name_loc.start), name_length);
760
752
 
761
- position_T start = prism_to_source_position(node->location.start, prism_source_start, source_base_offset, source);
762
- position_T end = prism_to_source_position(node->location.end, prism_source_start, source_base_offset, source);
753
+ position_T start = prism_to_source_position(node->location.start, source_base_offset, source);
754
+ position_T end = prism_to_source_position(herb_prism_location_end(node->location), source_base_offset, source);
763
755
 
764
756
  AST_RUBY_LITERAL_NODE_T* default_value = NULL;
765
757
 
766
758
  if (optional->value) {
767
- size_t value_length = (size_t) (optional->value->location.end - optional->value->location.start);
768
- char* value_string = hb_allocator_strndup(allocator, (const char*) optional->value->location.start, value_length);
769
- position_T value_start =
770
- prism_to_source_position(optional->value->location.start, prism_source_start, source_base_offset, source);
759
+ size_t value_length = optional->value->location.length;
760
+ char* value_string = hb_allocator_strndup(
761
+ allocator,
762
+ (const char*) (prism_source_start + optional->value->location.start),
763
+ value_length
764
+ );
765
+ position_T value_start = prism_to_source_position(optional->value->location.start, source_base_offset, source);
771
766
  position_T value_end =
772
- prism_to_source_position(optional->value->location.end, prism_source_start, source_base_offset, source);
767
+ prism_to_source_position(herb_prism_location_end(optional->value->location), source_base_offset, source);
773
768
 
774
769
  default_value = ast_ruby_literal_node_init(
775
770
  hb_string_from_c_string(value_string),
@@ -783,7 +778,7 @@ hb_array_T* extract_parameters_from_prism(
783
778
 
784
779
  append_parameter(
785
780
  result,
786
- create_parameter_name_token(optional->name_loc, name, prism_source_start, source_base_offset, source, allocator),
781
+ create_parameter_name_token(optional->name_loc, name, source_base_offset, source, allocator),
787
782
  default_value,
788
783
  "positional",
789
784
  false,
@@ -800,17 +795,17 @@ hb_array_T* extract_parameters_from_prism(
800
795
  pm_rest_parameter_node_t* rest = (pm_rest_parameter_node_t*) parameters->rest;
801
796
 
802
797
  if (rest->name) {
803
- size_t name_length = (size_t) (rest->name_loc.end - rest->name_loc.start);
804
- char* name = hb_allocator_strndup(allocator, (const char*) rest->name_loc.start, name_length);
798
+ size_t name_length = rest->name_loc.length;
799
+ char* name =
800
+ hb_allocator_strndup(allocator, (const char*) (prism_source_start + rest->name_loc.start), name_length);
805
801
 
806
- position_T start =
807
- prism_to_source_position(parameters->rest->location.start, prism_source_start, source_base_offset, source);
802
+ position_T start = prism_to_source_position(parameters->rest->location.start, source_base_offset, source);
808
803
  position_T end =
809
- prism_to_source_position(parameters->rest->location.end, prism_source_start, source_base_offset, source);
804
+ prism_to_source_position(herb_prism_location_end(parameters->rest->location), source_base_offset, source);
810
805
 
811
806
  append_parameter(
812
807
  result,
813
- create_parameter_name_token(rest->name_loc, name, prism_source_start, source_base_offset, source, allocator),
808
+ create_parameter_name_token(rest->name_loc, name, source_base_offset, source, allocator),
814
809
  NULL,
815
810
  "rest",
816
811
  false,
@@ -827,8 +822,8 @@ hb_array_T* extract_parameters_from_prism(
827
822
  NULL,
828
823
  "rest",
829
824
  false,
830
- prism_to_source_position(parameters->rest->location.start, prism_source_start, source_base_offset, source),
831
- prism_to_source_position(parameters->rest->location.end, prism_source_start, source_base_offset, source),
825
+ prism_to_source_position(parameters->rest->location.start, source_base_offset, source),
826
+ prism_to_source_position(herb_prism_location_end(parameters->rest->location), source_base_offset, source),
832
827
  allocator
833
828
  );
834
829
  }
@@ -863,21 +858,18 @@ hb_array_T* extract_parameters_from_prism(
863
858
  name_location = optional_keyword->name_loc;
864
859
 
865
860
  if (optional_keyword->value) {
866
- size_t value_length =
867
- (size_t) (optional_keyword->value->location.end - optional_keyword->value->location.start);
868
- char* value_string =
869
- hb_allocator_strndup(allocator, (const char*) optional_keyword->value->location.start, value_length);
870
-
871
- position_T value_start = prism_to_source_position(
872
- optional_keyword->value->location.start,
873
- prism_source_start,
874
- source_base_offset,
875
- source
861
+ size_t value_length = optional_keyword->value->location.length;
862
+ char* value_string = hb_allocator_strndup(
863
+ allocator,
864
+ (const char*) (prism_source_start + optional_keyword->value->location.start),
865
+ value_length
876
866
  );
877
867
 
868
+ position_T value_start =
869
+ prism_to_source_position(optional_keyword->value->location.start, source_base_offset, source);
870
+
878
871
  position_T value_end = prism_to_source_position(
879
- optional_keyword->value->location.end,
880
- prism_source_start,
872
+ herb_prism_location_end(optional_keyword->value->location),
881
873
  source_base_offset,
882
874
  source
883
875
  );
@@ -896,17 +888,16 @@ hb_array_T* extract_parameters_from_prism(
896
888
  continue;
897
889
  }
898
890
 
899
- size_t name_length = (size_t) (name_location.end - name_location.start);
900
- if (name_length > 0 && name_location.start[name_length - 1] == ':') { name_length--; }
901
- char* name = hb_allocator_strndup(allocator, (const char*) name_location.start, name_length);
891
+ size_t name_length = name_location.length;
892
+ if (name_length > 0 && prism_source_start[name_location.start + name_length - 1] == ':') { name_length--; }
893
+ char* name = hb_allocator_strndup(allocator, (const char*) (prism_source_start + name_location.start), name_length);
902
894
 
903
- position_T start =
904
- prism_to_source_position(keyword->location.start, prism_source_start, source_base_offset, source);
905
- position_T end = prism_to_source_position(keyword->location.end, prism_source_start, source_base_offset, source);
895
+ position_T start = prism_to_source_position(keyword->location.start, source_base_offset, source);
896
+ position_T end = prism_to_source_position(herb_prism_location_end(keyword->location), source_base_offset, source);
906
897
 
907
898
  append_parameter(
908
899
  result,
909
- create_parameter_name_token(name_location, name, prism_source_start, source_base_offset, source, allocator),
900
+ create_parameter_name_token(name_location, name, source_base_offset, source, allocator),
910
901
  default_value,
911
902
  "keyword",
912
903
  is_required,
@@ -922,30 +913,19 @@ hb_array_T* extract_parameters_from_prism(
922
913
  if (parameters->keyword_rest && parameters->keyword_rest->type == PM_KEYWORD_REST_PARAMETER_NODE) {
923
914
  pm_keyword_rest_parameter_node_t* keyword_rest = (pm_keyword_rest_parameter_node_t*) parameters->keyword_rest;
924
915
 
925
- position_T start = prism_to_source_position(
926
- parameters->keyword_rest->location.start,
927
- prism_source_start,
928
- source_base_offset,
929
- source
930
- );
916
+ position_T start = prism_to_source_position(parameters->keyword_rest->location.start, source_base_offset, source);
931
917
 
932
918
  position_T end =
933
- prism_to_source_position(parameters->keyword_rest->location.end, prism_source_start, source_base_offset, source);
919
+ prism_to_source_position(herb_prism_location_end(parameters->keyword_rest->location), source_base_offset, source);
934
920
 
935
921
  if (keyword_rest->name) {
936
- size_t name_length = (size_t) (keyword_rest->name_loc.end - keyword_rest->name_loc.start);
937
- char* name = hb_allocator_strndup(allocator, (const char*) keyword_rest->name_loc.start, name_length);
922
+ size_t name_length = keyword_rest->name_loc.length;
923
+ char* name =
924
+ hb_allocator_strndup(allocator, (const char*) (prism_source_start + keyword_rest->name_loc.start), name_length);
938
925
 
939
926
  append_parameter(
940
927
  result,
941
- create_parameter_name_token(
942
- keyword_rest->name_loc,
943
- name,
944
- prism_source_start,
945
- source_base_offset,
946
- source,
947
- allocator
948
- ),
928
+ create_parameter_name_token(keyword_rest->name_loc, name, source_base_offset, source, allocator),
949
929
  NULL,
950
930
  "keyword_rest",
951
931
  false,
@@ -962,28 +942,21 @@ hb_array_T* extract_parameters_from_prism(
962
942
  }
963
943
 
964
944
  // Block: |&blk|
965
- if (parameters->block) {
966
- pm_block_parameter_node_t* block_param = parameters->block;
945
+ if (parameters->block && parameters->block->type == PM_BLOCK_PARAMETER_NODE) {
946
+ pm_block_parameter_node_t* block_param = (pm_block_parameter_node_t*) parameters->block;
967
947
 
968
948
  if (block_param->name) {
969
- size_t name_length = (size_t) (block_param->name_loc.end - block_param->name_loc.start);
970
- char* name = hb_allocator_strndup(allocator, (const char*) block_param->name_loc.start, name_length);
949
+ size_t name_length = block_param->name_loc.length;
950
+ char* name =
951
+ hb_allocator_strndup(allocator, (const char*) (prism_source_start + block_param->name_loc.start), name_length);
971
952
 
972
- position_T start =
973
- prism_to_source_position(block_param->base.location.start, prism_source_start, source_base_offset, source);
953
+ position_T start = prism_to_source_position(block_param->base.location.start, source_base_offset, source);
974
954
  position_T end =
975
- prism_to_source_position(block_param->base.location.end, prism_source_start, source_base_offset, source);
955
+ prism_to_source_position(herb_prism_location_end(block_param->base.location), source_base_offset, source);
976
956
 
977
957
  append_parameter(
978
958
  result,
979
- create_parameter_name_token(
980
- block_param->name_loc,
981
- name,
982
- prism_source_start,
983
- source_base_offset,
984
- source,
985
- allocator
986
- ),
959
+ create_parameter_name_token(block_param->name_loc, name, source_base_offset, source, allocator),
987
960
  NULL,
988
961
  "block",
989
962
  false,
@@ -1000,8 +973,8 @@ hb_array_T* extract_parameters_from_prism(
1000
973
  NULL,
1001
974
  "block",
1002
975
  false,
1003
- prism_to_source_position(block_param->base.location.start, prism_source_start, source_base_offset, source),
1004
- prism_to_source_position(block_param->base.location.end, prism_source_start, source_base_offset, source),
976
+ prism_to_source_position(block_param->base.location.start, source_base_offset, source),
977
+ prism_to_source_position(herb_prism_location_end(block_param->base.location), source_base_offset, source),
1005
978
  allocator
1006
979
  );
1007
980
  }
@@ -1018,7 +991,7 @@ hb_array_T* extract_block_arguments_from_erb_node(
1018
991
  ) {
1019
992
  if (!erb_node || !erb_node->analyzed_ruby || !erb_node->analyzed_ruby->parsed) { return hb_array_init(0, allocator); }
1020
993
 
1021
- pm_parser_t* parser = &erb_node->analyzed_ruby->parser;
994
+ pm_parser_t* parser = erb_node->analyzed_ruby->parser;
1022
995
  pm_block_node_t* block_node = find_first_block_node(erb_node->analyzed_ruby->root);
1023
996
 
1024
997
  if (!block_node || !block_node->parameters) { return hb_array_init(0, allocator); }
@@ -1031,17 +1004,17 @@ hb_array_T* extract_block_arguments_from_erb_node(
1031
1004
  erb_content_offset = calculate_byte_offset_from_position(source, erb_node->content->location.start);
1032
1005
  }
1033
1006
 
1034
- const uint8_t* prism_source_start = (const uint8_t*) parser->start;
1007
+ const uint8_t* prism_source_start = pm_parser_start(parser);
1035
1008
 
1036
1009
  if (errors) {
1037
- for (const pm_diagnostic_t* error = (const pm_diagnostic_t*) parser->error_list.head; error != NULL;
1038
- error = (const pm_diagnostic_t*) error->node.next) {
1010
+ for (const pm_diagnostic_t* error = pm_parser_errors_first(parser); error != NULL;
1011
+ error = pm_diagnostic_next(error)) {
1039
1012
  if (error->diag_id == PM_ERR_BLOCK_TERM_END) { continue; }
1040
1013
  if (error->diag_id == PM_ERR_BLOCK_TERM_BRACE) { continue; }
1041
1014
  if (error->diag_id == PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT) { continue; }
1042
1015
 
1043
- size_t error_start_offset = (size_t) (error->location.start - prism_source_start);
1044
- size_t error_end_offset = (size_t) (error->location.end - prism_source_start);
1016
+ size_t error_start_offset = error->location.start;
1017
+ size_t error_end_offset = herb_prism_location_end(error->location);
1045
1018
 
1046
1019
  position_T error_start = byte_offset_to_position(source, erb_content_offset + error_start_offset);
1047
1020
  position_T error_end = byte_offset_to_position(source, erb_content_offset + error_end_offset);
@@ -1100,7 +1073,7 @@ static bool is_plain_decimal_integer(hb_string_T source) {
1100
1073
  return true;
1101
1074
  }
1102
1075
 
1103
- static bool prism_node_static_output(const pm_node_t* node, hb_string_T* output) {
1076
+ static bool prism_node_static_output(const uint8_t* source, const pm_node_t* node, hb_string_T* output) {
1104
1077
  if (!node || !output) { return false; }
1105
1078
 
1106
1079
  switch (node->type) {
@@ -1119,12 +1092,11 @@ static bool prism_node_static_output(const pm_node_t* node, hb_string_T* output)
1119
1092
  }
1120
1093
 
1121
1094
  case PM_INTEGER_NODE: {
1122
- hb_string_T source =
1123
- hb_string_from_data((const char*) node->location.start, (size_t) (node->location.end - node->location.start));
1095
+ hb_string_T integer = hb_string_from_data((const char*) (source + node->location.start), node->location.length);
1124
1096
 
1125
- if (!is_plain_decimal_integer(source)) { return false; }
1097
+ if (!is_plain_decimal_integer(integer)) { return false; }
1126
1098
 
1127
- *output = source;
1099
+ *output = integer;
1128
1100
  break;
1129
1101
  }
1130
1102
 
@@ -1173,17 +1145,18 @@ bool append_static_output_node(
1173
1145
  if (body->body.size != 1) { return false; }
1174
1146
 
1175
1147
  const pm_node_t* literal = body->body.nodes[0];
1176
- const uint8_t* parser_start = analyzed->parser.start;
1148
+ const uint8_t* parser_start = pm_parser_start(analyzed->parser);
1149
+ size_t source_length = (size_t) (pm_parser_end(analyzed->parser) - parser_start);
1177
1150
 
1178
- if (literal->location.start < parser_start || literal->location.end > analyzed->parser.end) { return false; }
1151
+ if (herb_prism_location_end(literal->location) > source_length) { return false; }
1179
1152
 
1180
1153
  hb_string_T content;
1181
1154
 
1182
- if (!prism_node_static_output(literal, &content)) { return false; }
1155
+ if (!prism_node_static_output(parser_start, literal, &content)) { return false; }
1183
1156
  if (content.length == 0) { return true; }
1184
1157
 
1185
- size_t offset = (size_t) (literal->location.start - parser_start);
1186
- size_t length = (size_t) (literal->location.end - literal->location.start);
1158
+ size_t offset = literal->location.start;
1159
+ size_t length = literal->location.length;
1187
1160
 
1188
1161
  position_T start_position = { .line = content_start.line, .column = content_start.column + (uint32_t) offset };
1189
1162
  position_T end_position = { .line = content_start.line,