herb 0.8.6 → 0.8.8

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +7 -0
  3. data/config.yml +12 -0
  4. data/ext/herb/error_helpers.c +1 -1
  5. data/ext/herb/extconf.rb +0 -4
  6. data/ext/herb/extension_helpers.c +1 -1
  7. data/ext/herb/nodes.c +18 -10
  8. data/lib/herb/ast/nodes.rb +32 -8
  9. data/lib/herb/engine/debug_visitor.rb +1 -1
  10. data/lib/herb/version.rb +1 -1
  11. data/lib/herb.rb +30 -3
  12. data/sig/herb/ast/nodes.rbs +16 -8
  13. data/sig/serialized_ast_nodes.rbs +4 -0
  14. data/src/analyze.c +137 -42
  15. data/src/analyze_helpers.c +80 -12
  16. data/src/analyzed_ruby.c +1 -0
  17. data/src/ast_node.c +1 -1
  18. data/src/ast_nodes.c +65 -161
  19. data/src/ast_pretty_print.c +52 -0
  20. data/src/errors.c +5 -5
  21. data/src/extract.c +2 -2
  22. data/src/herb.c +2 -2
  23. data/src/include/analyze_helpers.h +7 -0
  24. data/src/include/analyzed_ruby.h +1 -0
  25. data/src/include/ast_nodes.h +8 -4
  26. data/src/include/location.h +4 -0
  27. data/src/include/prism_helpers.h +6 -0
  28. data/src/include/util/hb_narray.h +1 -0
  29. data/src/include/version.h +1 -1
  30. data/src/location.c +16 -0
  31. data/src/parser.c +9 -9
  32. data/src/parser_helpers.c +4 -4
  33. data/src/pretty_print.c +6 -6
  34. data/src/prism_helpers.c +188 -0
  35. data/src/util/hb_array.c +1 -0
  36. data/src/util/hb_narray.c +6 -0
  37. data/src/visitor.c +26 -26
  38. data/templates/ext/herb/error_helpers.c.erb +1 -1
  39. data/templates/ext/herb/nodes.c.erb +3 -1
  40. data/templates/java/error_helpers.c.erb +1 -1
  41. data/templates/java/nodes.c.erb +5 -3
  42. data/templates/java/org/herb/ast/Nodes.java.erb +11 -0
  43. data/templates/javascript/packages/core/src/nodes.ts.erb +14 -0
  44. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +1 -1
  45. data/templates/javascript/packages/node/extension/nodes.cpp.erb +10 -1
  46. data/templates/lib/herb/ast/nodes.rb.erb +4 -0
  47. data/templates/rust/src/ast/nodes.rs.erb +12 -2
  48. data/templates/rust/src/nodes.rs.erb +4 -0
  49. data/templates/src/ast_nodes.c.erb +7 -7
  50. data/templates/src/ast_pretty_print.c.erb +14 -0
  51. data/templates/src/errors.c.erb +5 -5
  52. data/templates/src/visitor.c.erb +1 -1
  53. data/templates/template.rb +11 -0
  54. data/templates/wasm/error_helpers.cpp.erb +1 -1
  55. data/templates/wasm/nodes.cpp.erb +7 -1
  56. data/vendor/prism/include/prism/version.h +2 -2
  57. data/vendor/prism/src/prism.c +48 -27
  58. data/vendor/prism/templates/java/org/prism/Loader.java.erb +1 -1
  59. data/vendor/prism/templates/javascript/src/deserialize.js.erb +1 -1
  60. data/vendor/prism/templates/lib/prism/compiler.rb.erb +2 -2
  61. data/vendor/prism/templates/lib/prism/node.rb.erb +24 -1
  62. data/vendor/prism/templates/lib/prism/serialize.rb.erb +1 -1
  63. data/vendor/prism/templates/lib/prism/visitor.rb.erb +2 -2
  64. data/vendor/prism/templates/sig/prism/node.rbs.erb +1 -0
  65. metadata +2 -2
@@ -265,6 +265,19 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
265
265
  pretty_print_token_property(erb_if_node->tag_opening, hb_string("tag_opening"), indent, relative_indent, false, buffer);
266
266
  pretty_print_token_property(erb_if_node->content, hb_string("content"), indent, relative_indent, false, buffer);
267
267
  pretty_print_token_property(erb_if_node->tag_closing, hb_string("tag_closing"), indent, relative_indent, false, buffer);
268
+ pretty_print_label(hb_string("then_keyword"), indent, relative_indent, false, buffer);
269
+ if (erb_if_node->then_keyword) {
270
+ char then_keyword_location_string[128];
271
+ sprintf(then_keyword_location_string, " (location: (%u:%u)-(%u:%u))\n",
272
+ erb_if_node->then_keyword->start.line,
273
+ erb_if_node->then_keyword->start.column,
274
+ erb_if_node->then_keyword->end.line,
275
+ erb_if_node->then_keyword->end.column);
276
+ hb_buffer_append(buffer, then_keyword_location_string);
277
+ } else {
278
+ hb_buffer_append(buffer, " ∅\n");
279
+ }
280
+
268
281
  pretty_print_array(hb_string("statements"), erb_if_node->statements, indent, relative_indent, false, buffer);
269
282
 
270
283
  pretty_print_label(hb_string("subsequent"), indent, relative_indent, false, buffer);
@@ -330,6 +343,19 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
330
343
  pretty_print_token_property(erb_when_node->tag_opening, hb_string("tag_opening"), indent, relative_indent, false, buffer);
331
344
  pretty_print_token_property(erb_when_node->content, hb_string("content"), indent, relative_indent, false, buffer);
332
345
  pretty_print_token_property(erb_when_node->tag_closing, hb_string("tag_closing"), indent, relative_indent, false, buffer);
346
+ pretty_print_label(hb_string("then_keyword"), indent, relative_indent, false, buffer);
347
+ if (erb_when_node->then_keyword) {
348
+ char then_keyword_location_string[128];
349
+ sprintf(then_keyword_location_string, " (location: (%u:%u)-(%u:%u))\n",
350
+ erb_when_node->then_keyword->start.line,
351
+ erb_when_node->then_keyword->start.column,
352
+ erb_when_node->then_keyword->end.line,
353
+ erb_when_node->then_keyword->end.column);
354
+ hb_buffer_append(buffer, then_keyword_location_string);
355
+ } else {
356
+ hb_buffer_append(buffer, " ∅\n");
357
+ }
358
+
333
359
  pretty_print_array(hb_string("statements"), erb_when_node->statements, indent, relative_indent, true, buffer);
334
360
  } break;
335
361
 
@@ -602,6 +628,19 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
602
628
  pretty_print_token_property(erb_unless_node->tag_opening, hb_string("tag_opening"), indent, relative_indent, false, buffer);
603
629
  pretty_print_token_property(erb_unless_node->content, hb_string("content"), indent, relative_indent, false, buffer);
604
630
  pretty_print_token_property(erb_unless_node->tag_closing, hb_string("tag_closing"), indent, relative_indent, false, buffer);
631
+ pretty_print_label(hb_string("then_keyword"), indent, relative_indent, false, buffer);
632
+ if (erb_unless_node->then_keyword) {
633
+ char then_keyword_location_string[128];
634
+ sprintf(then_keyword_location_string, " (location: (%u:%u)-(%u:%u))\n",
635
+ erb_unless_node->then_keyword->start.line,
636
+ erb_unless_node->then_keyword->start.column,
637
+ erb_unless_node->then_keyword->end.line,
638
+ erb_unless_node->then_keyword->end.column);
639
+ hb_buffer_append(buffer, then_keyword_location_string);
640
+ } else {
641
+ hb_buffer_append(buffer, " ∅\n");
642
+ }
643
+
605
644
  pretty_print_array(hb_string("statements"), erb_unless_node->statements, indent, relative_indent, false, buffer);
606
645
 
607
646
  pretty_print_label(hb_string("else_clause"), indent, relative_indent, false, buffer);
@@ -651,6 +690,19 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
651
690
  pretty_print_token_property(erb_in_node->tag_opening, hb_string("tag_opening"), indent, relative_indent, false, buffer);
652
691
  pretty_print_token_property(erb_in_node->content, hb_string("content"), indent, relative_indent, false, buffer);
653
692
  pretty_print_token_property(erb_in_node->tag_closing, hb_string("tag_closing"), indent, relative_indent, false, buffer);
693
+ pretty_print_label(hb_string("then_keyword"), indent, relative_indent, false, buffer);
694
+ if (erb_in_node->then_keyword) {
695
+ char then_keyword_location_string[128];
696
+ sprintf(then_keyword_location_string, " (location: (%u:%u)-(%u:%u))\n",
697
+ erb_in_node->then_keyword->start.line,
698
+ erb_in_node->then_keyword->start.column,
699
+ erb_in_node->then_keyword->end.line,
700
+ erb_in_node->then_keyword->end.column);
701
+ hb_buffer_append(buffer, then_keyword_location_string);
702
+ } else {
703
+ hb_buffer_append(buffer, " ∅\n");
704
+ }
705
+
654
706
  pretty_print_array(hb_string("statements"), erb_in_node->statements, indent, relative_indent, true, buffer);
655
707
  } break;
656
708
 
data/src/errors.c CHANGED
@@ -667,7 +667,7 @@ void error_pretty_print_array(
667
667
  return;
668
668
  }
669
669
 
670
- if (array->size == 0) {
670
+ if (hb_array_size(array) == 0) {
671
671
  pretty_print_property(hb_string(name), hb_string("[]"), indent, relative_indent, last_property, buffer);
672
672
 
673
673
  return;
@@ -678,17 +678,17 @@ void error_pretty_print_array(
678
678
  hb_buffer_append(buffer, "(");
679
679
 
680
680
  char count[16];
681
- sprintf(count, "%zu", array->size);
681
+ sprintf(count, "%zu", hb_array_size(array));
682
682
  hb_buffer_append(buffer, count);
683
683
  hb_buffer_append(buffer, ")\n");
684
684
 
685
685
  if (indent < 20) {
686
- for (size_t i = 0; i < array->size; i++) {
686
+ for (size_t i = 0; i < hb_array_size(array); i++) {
687
687
  ERROR_T* child = hb_array_get(array, i);
688
688
  pretty_print_indent(buffer, indent);
689
689
  pretty_print_indent(buffer, relative_indent + 1);
690
690
 
691
- if (i == array->size - 1) {
691
+ if (i == hb_array_size(array) - 1) {
692
692
  hb_buffer_append(buffer, "└── ");
693
693
  } else {
694
694
  hb_buffer_append(buffer, "├── ");
@@ -696,7 +696,7 @@ void error_pretty_print_array(
696
696
 
697
697
  error_pretty_print(child, indent + 1, relative_indent + 1, buffer);
698
698
 
699
- if (i != array->size - 1) { pretty_print_newline(indent + 1, relative_indent, buffer); }
699
+ if (i != hb_array_size(array) - 1) { pretty_print_newline(indent + 1, relative_indent, buffer); }
700
700
  }
701
701
  }
702
702
  }
data/src/extract.c CHANGED
@@ -12,7 +12,7 @@ void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output) {
12
12
  bool skip_erb_content = false;
13
13
  bool is_comment_tag = false;
14
14
 
15
- for (size_t i = 0; i < tokens->size; i++) {
15
+ for (size_t i = 0; i < hb_array_size(tokens); i++) {
16
16
  const token_T* token = hb_array_get(tokens, i);
17
17
 
18
18
  switch (token->type) {
@@ -95,7 +95,7 @@ void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output) {
95
95
  void herb_extract_html_to_buffer(const char* source, hb_buffer_T* output) {
96
96
  hb_array_T* tokens = herb_lex(source);
97
97
 
98
- for (size_t i = 0; i < tokens->size; i++) {
98
+ for (size_t i = 0; i < hb_array_size(tokens); i++) {
99
99
  const token_T* token = hb_array_get(tokens, i);
100
100
 
101
101
  switch (token->type) {
data/src/herb.c CHANGED
@@ -58,7 +58,7 @@ HERB_EXPORTED_FUNCTION hb_array_T* herb_lex_file(const char* path) {
58
58
  HERB_EXPORTED_FUNCTION void herb_lex_to_buffer(const char* source, hb_buffer_T* output) {
59
59
  hb_array_T* tokens = herb_lex(source);
60
60
 
61
- for (size_t i = 0; i < tokens->size; i++) {
61
+ for (size_t i = 0; i < hb_array_size(tokens); i++) {
62
62
  token_T* token = hb_array_get(tokens, i);
63
63
 
64
64
  hb_string_T type = token_to_string(token);
@@ -74,7 +74,7 @@ HERB_EXPORTED_FUNCTION void herb_lex_to_buffer(const char* source, hb_buffer_T*
74
74
  HERB_EXPORTED_FUNCTION void herb_free_tokens(hb_array_T** tokens) {
75
75
  if (!tokens || !*tokens) { return; }
76
76
 
77
- for (size_t i = 0; i < (*tokens)->size; i++) {
77
+ for (size_t i = 0; i < hb_array_size(*tokens); i++) {
78
78
  token_T* token = hb_array_get(*tokens, i);
79
79
  if (token) { token_free(token); }
80
80
  }
@@ -25,9 +25,15 @@ bool has_rescue_node(analyzed_ruby_T* analyzed);
25
25
  bool has_ensure_node(analyzed_ruby_T* analyzed);
26
26
  bool has_unless_node(analyzed_ruby_T* analyzed);
27
27
  bool has_yield_node(analyzed_ruby_T* analyzed);
28
+ bool has_then_keyword(analyzed_ruby_T* analyzed);
28
29
 
29
30
  bool has_error_message(analyzed_ruby_T* anlayzed, const char* message);
30
31
 
32
+ bool is_do_block(pm_location_t opening_location);
33
+ bool is_brace_block(pm_location_t opening_location);
34
+ bool is_closing_brace(pm_location_t location);
35
+ bool has_valid_block_closing(pm_location_t opening_loc, pm_location_t closing_loc);
36
+
31
37
  bool search_if_nodes(const pm_node_t* node, void* data);
32
38
  bool search_block_nodes(const pm_node_t* node, void* data);
33
39
  bool search_case_nodes(const pm_node_t* node, void* data);
@@ -46,6 +52,7 @@ bool search_in_nodes(analyzed_ruby_T* analyzed);
46
52
  bool search_rescue_nodes(analyzed_ruby_T* analyzed);
47
53
  bool search_ensure_nodes(analyzed_ruby_T* analyzed);
48
54
  bool search_yield_nodes(const pm_node_t* node, void* data);
55
+ bool search_then_keywords(const pm_node_t* node, void* data);
49
56
  bool search_unclosed_control_flows(const pm_node_t* node, void* data);
50
57
 
51
58
  void check_erb_node_for_missing_end(const AST_NODE_T* node);
@@ -29,6 +29,7 @@ typedef struct ANALYZED_RUBY_STRUCT {
29
29
  int ensure_node_count;
30
30
  int unless_node_count;
31
31
  int yield_node_count;
32
+ int then_keyword_count;
32
33
  int unclosed_control_flow_count;
33
34
  } analyzed_ruby_T;
34
35
 
@@ -183,6 +183,7 @@ typedef struct AST_ERB_IF_NODE_STRUCT {
183
183
  token_T* tag_opening;
184
184
  token_T* content;
185
185
  token_T* tag_closing;
186
+ location_T* then_keyword;
186
187
  hb_array_T* statements;
187
188
  struct AST_NODE_STRUCT* subsequent;
188
189
  struct AST_ERB_END_NODE_STRUCT* end_node;
@@ -202,6 +203,7 @@ typedef struct AST_ERB_WHEN_NODE_STRUCT {
202
203
  token_T* tag_opening;
203
204
  token_T* content;
204
205
  token_T* tag_closing;
206
+ location_T* then_keyword;
205
207
  hb_array_T* statements;
206
208
  } AST_ERB_WHEN_NODE_T;
207
209
 
@@ -288,6 +290,7 @@ typedef struct AST_ERB_UNLESS_NODE_STRUCT {
288
290
  token_T* tag_opening;
289
291
  token_T* content;
290
292
  token_T* tag_closing;
293
+ location_T* then_keyword;
291
294
  hb_array_T* statements;
292
295
  struct AST_ERB_ELSE_NODE_STRUCT* else_clause;
293
296
  struct AST_ERB_END_NODE_STRUCT* end_node;
@@ -305,6 +308,7 @@ typedef struct AST_ERB_IN_NODE_STRUCT {
305
308
  token_T* tag_opening;
306
309
  token_T* content;
307
310
  token_T* tag_closing;
311
+ location_T* then_keyword;
308
312
  hb_array_T* statements;
309
313
  } AST_ERB_IN_NODE_T;
310
314
 
@@ -325,9 +329,9 @@ AST_WHITESPACE_NODE_T* ast_whitespace_node_init(token_T* value, position_T start
325
329
  AST_ERB_CONTENT_NODE_T* ast_erb_content_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, analyzed_ruby_T* analyzed_ruby, bool parsed, bool valid, position_T start_position, position_T end_position, hb_array_T* errors);
326
330
  AST_ERB_END_NODE_T* ast_erb_end_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, position_T start_position, position_T end_position, hb_array_T* errors);
327
331
  AST_ERB_ELSE_NODE_T* ast_erb_else_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
328
- AST_ERB_IF_NODE_T* ast_erb_if_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_NODE_STRUCT* subsequent, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
332
+ AST_ERB_IF_NODE_T* ast_erb_if_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, location_T* then_keyword, hb_array_T* statements, struct AST_NODE_STRUCT* subsequent, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
329
333
  AST_ERB_BLOCK_NODE_T* ast_erb_block_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* body, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
330
- AST_ERB_WHEN_NODE_T* ast_erb_when_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
334
+ AST_ERB_WHEN_NODE_T* ast_erb_when_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, location_T* then_keyword, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
331
335
  AST_ERB_CASE_NODE_T* ast_erb_case_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* children, hb_array_T* conditions, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
332
336
  AST_ERB_CASE_MATCH_NODE_T* ast_erb_case_match_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* children, hb_array_T* conditions, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
333
337
  AST_ERB_WHILE_NODE_T* ast_erb_while_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
@@ -336,9 +340,9 @@ AST_ERB_FOR_NODE_T* ast_erb_for_node_init(token_T* tag_opening, token_T* content
336
340
  AST_ERB_RESCUE_NODE_T* ast_erb_rescue_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_ERB_RESCUE_NODE_STRUCT* subsequent, position_T start_position, position_T end_position, hb_array_T* errors);
337
341
  AST_ERB_ENSURE_NODE_T* ast_erb_ensure_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
338
342
  AST_ERB_BEGIN_NODE_T* ast_erb_begin_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_ERB_RESCUE_NODE_STRUCT* rescue_clause, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_ENSURE_NODE_STRUCT* ensure_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
339
- AST_ERB_UNLESS_NODE_T* ast_erb_unless_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
343
+ AST_ERB_UNLESS_NODE_T* ast_erb_unless_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, location_T* then_keyword, hb_array_T* statements, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
340
344
  AST_ERB_YIELD_NODE_T* ast_erb_yield_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, position_T start_position, position_T end_position, hb_array_T* errors);
341
- AST_ERB_IN_NODE_T* ast_erb_in_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
345
+ AST_ERB_IN_NODE_T* ast_erb_in_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, location_T* then_keyword, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
342
346
 
343
347
  hb_string_T ast_node_type_to_string(AST_NODE_T* node);
344
348
  hb_string_T ast_node_human_type(AST_NODE_T* node);
@@ -19,4 +19,8 @@ void location_from(
19
19
  uint32_t end_column
20
20
  );
21
21
 
22
+ void location_from_positions(location_T* location, position_T start, position_T end);
23
+
24
+ location_T* location_create(position_T start, position_T end);
25
+
22
26
  #endif
@@ -1,8 +1,10 @@
1
1
  #ifndef HERB_PRISM_HELPERS_H
2
2
  #define HERB_PRISM_HELPERS_H
3
3
 
4
+ #include "analyzed_ruby.h"
4
5
  #include "ast_nodes.h"
5
6
  #include "errors.h"
7
+ #include "location.h"
6
8
  #include "position.h"
7
9
 
8
10
  #include <prism.h>
@@ -22,4 +24,8 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
22
24
  position_T end
23
25
  );
24
26
 
27
+ location_T* get_then_keyword_location(analyzed_ruby_T* analyzed, const char* source);
28
+ location_T* get_then_keyword_location_wrapped(const char* source, bool is_in_clause);
29
+ location_T* get_then_keyword_location_elsif_wrapped(const char* source);
30
+
25
31
  #endif
@@ -18,6 +18,7 @@ void hb_narray_init(hb_narray_T* array, size_t item_size, size_t initial_capacit
18
18
  void* hb_narray_get(const hb_narray_T* array, size_t index);
19
19
  void* hb_narray_first(hb_narray_T* array);
20
20
  void* hb_narray_last(hb_narray_T* array);
21
+ size_t hb_narray_size(const hb_narray_T* array);
21
22
 
22
23
  void hb_narray_append(hb_narray_T* array, void* item);
23
24
  void hb_narray_remove(hb_narray_T* array, size_t index);
@@ -1,6 +1,6 @@
1
1
  #ifndef HERB_VERSION_H
2
2
  #define HERB_VERSION_H
3
3
 
4
- #define HERB_VERSION "0.8.6"
4
+ #define HERB_VERSION "0.8.8"
5
5
 
6
6
  #endif
data/src/location.c CHANGED
@@ -11,3 +11,19 @@ void location_from(
11
11
  location->start = (position_T) { .line = start_line, .column = start_column };
12
12
  location->end = (position_T) { .line = end_line, .column = end_column };
13
13
  }
14
+
15
+ void location_from_positions(location_T* location, position_T start, position_T end) {
16
+ location->start = start;
17
+ location->end = end;
18
+ }
19
+
20
+ location_T* location_create(position_T start, position_T end) {
21
+ location_T* location = malloc(sizeof(location_T));
22
+
23
+ if (location != NULL) {
24
+ location->start = start;
25
+ location->end = end;
26
+ }
27
+
28
+ return location;
29
+ }
data/src/parser.c CHANGED
@@ -314,7 +314,7 @@ static AST_HTML_ATTRIBUTE_NAME_NODE_T* parser_parse_html_attribute_name(parser_T
314
314
  position_T node_start = { 0 };
315
315
  position_T node_end = { 0 };
316
316
 
317
- if (children->size > 0) {
317
+ if (hb_array_size(children) > 0) {
318
318
  AST_NODE_T* first_child = hb_array_first(children);
319
319
  AST_NODE_T* last_child = hb_array_last(children);
320
320
 
@@ -1144,7 +1144,7 @@ static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, h
1144
1144
  static size_t find_matching_close_tag(hb_array_T* nodes, size_t start_idx, hb_string_T tag_name) {
1145
1145
  int depth = 0;
1146
1146
 
1147
- for (size_t i = start_idx + 1; i < nodes->size; i++) {
1147
+ for (size_t i = start_idx + 1; i < hb_array_size(nodes); i++) {
1148
1148
  AST_NODE_T* node = (AST_NODE_T*) hb_array_get(nodes, i);
1149
1149
  if (node == NULL) { continue; }
1150
1150
 
@@ -1168,9 +1168,9 @@ static size_t find_matching_close_tag(hb_array_T* nodes, size_t start_idx, hb_st
1168
1168
  static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T* errors);
1169
1169
 
1170
1170
  static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T* errors) {
1171
- hb_array_T* result = hb_array_init(nodes->size);
1171
+ hb_array_T* result = hb_array_init(hb_array_size(nodes));
1172
1172
 
1173
- for (size_t index = 0; index < nodes->size; index++) {
1173
+ for (size_t index = 0; index < hb_array_size(nodes); index++) {
1174
1174
  AST_NODE_T* node = (AST_NODE_T*) hb_array_get(nodes, index);
1175
1175
  if (node == NULL) { continue; }
1176
1176
 
@@ -1181,7 +1181,7 @@ static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T
1181
1181
  size_t close_index = find_matching_close_tag(nodes, index, tag_name);
1182
1182
 
1183
1183
  if (close_index == (size_t) -1) {
1184
- if (open_tag->base.errors->size == 0) {
1184
+ if (hb_array_size(open_tag->base.errors) == 0) {
1185
1185
  append_missing_closing_tag_error(
1186
1186
  open_tag->tag_name,
1187
1187
  open_tag->base.location.start,
@@ -1225,7 +1225,7 @@ static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T
1225
1225
  AST_HTML_CLOSE_TAG_NODE_T* close_tag = (AST_HTML_CLOSE_TAG_NODE_T*) node;
1226
1226
 
1227
1227
  if (!is_void_element(hb_string(close_tag->tag_name->value))) {
1228
- if (close_tag->base.errors->size == 0) {
1228
+ if (hb_array_size(close_tag->base.errors) == 0) {
1229
1229
  append_missing_opening_tag_error(
1230
1230
  close_tag->tag_name,
1231
1231
  close_tag->base.location.start,
@@ -1299,19 +1299,19 @@ void herb_parser_deinit(parser_T* parser) {
1299
1299
  }
1300
1300
 
1301
1301
  void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors) {
1302
- if (nodes == NULL || nodes->size == 0) { return; }
1302
+ if (nodes == NULL || hb_array_size(nodes) == 0) { return; }
1303
1303
 
1304
1304
  hb_array_T* processed = parser_build_elements_from_tags(nodes, errors);
1305
1305
 
1306
1306
  nodes->size = 0;
1307
1307
 
1308
- for (size_t i = 0; i < processed->size; i++) {
1308
+ for (size_t i = 0; i < hb_array_size(processed); i++) {
1309
1309
  hb_array_append(nodes, hb_array_get(processed, i));
1310
1310
  }
1311
1311
 
1312
1312
  hb_array_free(&processed);
1313
1313
 
1314
- for (size_t i = 0; i < nodes->size; i++) {
1314
+ for (size_t i = 0; i < hb_array_size(nodes); i++) {
1315
1315
  AST_NODE_T* node = (AST_NODE_T*) hb_array_get(nodes, i);
1316
1316
  if (node == NULL) { continue; }
1317
1317
 
data/src/parser_helpers.c CHANGED
@@ -19,7 +19,7 @@ void parser_push_open_tag(const parser_T* parser, token_T* tag_name) {
19
19
  }
20
20
 
21
21
  bool parser_check_matching_tag(const parser_T* parser, hb_string_T tag_name) {
22
- if (parser->open_tags_stack->size == 0) { return false; }
22
+ if (hb_array_size(parser->open_tags_stack) == 0) { return false; }
23
23
 
24
24
  token_T* top_token = hb_array_last(parser->open_tags_stack);
25
25
  if (top_token == NULL || top_token->value == NULL) { return false; };
@@ -28,7 +28,7 @@ bool parser_check_matching_tag(const parser_T* parser, hb_string_T tag_name) {
28
28
  }
29
29
 
30
30
  token_T* parser_pop_open_tag(const parser_T* parser) {
31
- if (parser->open_tags_stack->size == 0) { return NULL; }
31
+ if (hb_array_size(parser->open_tags_stack) == 0) { return NULL; }
32
32
 
33
33
  return hb_array_pop(parser->open_tags_stack);
34
34
  }
@@ -42,7 +42,7 @@ token_T* parser_pop_open_tag(const parser_T* parser) {
42
42
  bool parser_in_svg_context(const parser_T* parser) {
43
43
  if (!parser || !parser->open_tags_stack) { return false; }
44
44
 
45
- size_t stack_size = parser->open_tags_stack->size;
45
+ size_t stack_size = hb_array_size(parser->open_tags_stack);
46
46
 
47
47
  for (size_t i = 0; i < stack_size; i++) {
48
48
  token_T* tag = (token_T*) hb_array_get(parser->open_tags_stack, i);
@@ -191,7 +191,7 @@ void parser_handle_mismatched_tags(
191
191
  const AST_HTML_CLOSE_TAG_NODE_T* close_tag,
192
192
  hb_array_T* errors
193
193
  ) {
194
- if (parser->open_tags_stack->size > 0) {
194
+ if (hb_array_size(parser->open_tags_stack) > 0) {
195
195
  token_T* expected_tag = hb_array_last(parser->open_tags_stack);
196
196
  token_T* actual_tag = close_tag->tag_name;
197
197
 
data/src/pretty_print.c CHANGED
@@ -113,7 +113,7 @@ void pretty_print_array(
113
113
  return;
114
114
  }
115
115
 
116
- if (array->size == 0) {
116
+ if (hb_array_size(array) == 0) {
117
117
  pretty_print_property(name, hb_string("[]"), indent, relative_indent, last_property, buffer);
118
118
 
119
119
  return;
@@ -124,17 +124,17 @@ void pretty_print_array(
124
124
  hb_buffer_append(buffer, "(");
125
125
 
126
126
  char count[16];
127
- sprintf(count, "%zu", array->size);
127
+ sprintf(count, "%zu", hb_array_size(array));
128
128
  hb_buffer_append(buffer, count);
129
129
  hb_buffer_append(buffer, ")\n");
130
130
 
131
131
  if (indent < 20) {
132
- for (size_t i = 0; i < array->size; i++) {
132
+ for (size_t i = 0; i < hb_array_size(array); i++) {
133
133
  AST_NODE_T* child = hb_array_get(array, i);
134
134
  pretty_print_indent(buffer, indent);
135
135
  pretty_print_indent(buffer, relative_indent + 1);
136
136
 
137
- if (i == array->size - 1) {
137
+ if (i == hb_array_size(array) - 1) {
138
138
  hb_buffer_append(buffer, "└── ");
139
139
  } else {
140
140
  hb_buffer_append(buffer, "├── ");
@@ -142,7 +142,7 @@ void pretty_print_array(
142
142
 
143
143
  ast_pretty_print_node(child, indent + 1, relative_indent + 1, buffer);
144
144
 
145
- if (i != array->size - 1) { pretty_print_newline(indent + 1, relative_indent, buffer); }
145
+ if (i != hb_array_size(array) - 1) { pretty_print_newline(indent + 1, relative_indent, buffer); }
146
146
  }
147
147
  }
148
148
  hb_buffer_append(buffer, "\n");
@@ -155,7 +155,7 @@ void pretty_print_errors(
155
155
  const bool last_property,
156
156
  hb_buffer_T* buffer
157
157
  ) {
158
- if (node->errors != NULL && node->errors->size > 0) {
158
+ if (hb_array_size(node->errors) > 0) {
159
159
  error_pretty_print_array("errors", node->errors, indent, relative_indent, last_property, buffer);
160
160
  hb_buffer_append(buffer, "\n");
161
161
  }