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.
- checksums.yaml +4 -4
- data/Rakefile +7 -0
- data/config.yml +12 -0
- data/ext/herb/error_helpers.c +1 -1
- data/ext/herb/extconf.rb +0 -4
- data/ext/herb/extension_helpers.c +1 -1
- data/ext/herb/nodes.c +18 -10
- data/lib/herb/ast/nodes.rb +32 -8
- data/lib/herb/engine/debug_visitor.rb +1 -1
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +30 -3
- data/sig/herb/ast/nodes.rbs +16 -8
- data/sig/serialized_ast_nodes.rbs +4 -0
- data/src/analyze.c +137 -42
- data/src/analyze_helpers.c +80 -12
- data/src/analyzed_ruby.c +1 -0
- data/src/ast_node.c +1 -1
- data/src/ast_nodes.c +65 -161
- data/src/ast_pretty_print.c +52 -0
- data/src/errors.c +5 -5
- data/src/extract.c +2 -2
- data/src/herb.c +2 -2
- data/src/include/analyze_helpers.h +7 -0
- data/src/include/analyzed_ruby.h +1 -0
- data/src/include/ast_nodes.h +8 -4
- data/src/include/location.h +4 -0
- data/src/include/prism_helpers.h +6 -0
- data/src/include/util/hb_narray.h +1 -0
- data/src/include/version.h +1 -1
- data/src/location.c +16 -0
- data/src/parser.c +9 -9
- data/src/parser_helpers.c +4 -4
- data/src/pretty_print.c +6 -6
- data/src/prism_helpers.c +188 -0
- data/src/util/hb_array.c +1 -0
- data/src/util/hb_narray.c +6 -0
- data/src/visitor.c +26 -26
- data/templates/ext/herb/error_helpers.c.erb +1 -1
- data/templates/ext/herb/nodes.c.erb +3 -1
- data/templates/java/error_helpers.c.erb +1 -1
- data/templates/java/nodes.c.erb +5 -3
- data/templates/java/org/herb/ast/Nodes.java.erb +11 -0
- data/templates/javascript/packages/core/src/nodes.ts.erb +14 -0
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +1 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +10 -1
- data/templates/lib/herb/ast/nodes.rb.erb +4 -0
- data/templates/rust/src/ast/nodes.rs.erb +12 -2
- data/templates/rust/src/nodes.rs.erb +4 -0
- data/templates/src/ast_nodes.c.erb +7 -7
- data/templates/src/ast_pretty_print.c.erb +14 -0
- data/templates/src/errors.c.erb +5 -5
- data/templates/src/visitor.c.erb +1 -1
- data/templates/template.rb +11 -0
- data/templates/wasm/error_helpers.cpp.erb +1 -1
- data/templates/wasm/nodes.cpp.erb +7 -1
- data/vendor/prism/include/prism/version.h +2 -2
- data/vendor/prism/src/prism.c +48 -27
- data/vendor/prism/templates/java/org/prism/Loader.java.erb +1 -1
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +1 -1
- data/vendor/prism/templates/lib/prism/compiler.rb.erb +2 -2
- data/vendor/prism/templates/lib/prism/node.rb.erb +24 -1
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +1 -1
- data/vendor/prism/templates/lib/prism/visitor.rb.erb +2 -2
- data/vendor/prism/templates/sig/prism/node.rbs.erb +1 -0
- metadata +2 -2
data/src/ast_pretty_print.c
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
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);
|
data/src/include/analyzed_ruby.h
CHANGED
data/src/include/ast_nodes.h
CHANGED
|
@@ -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);
|
data/src/include/location.h
CHANGED
data/src/include/prism_helpers.h
CHANGED
|
@@ -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);
|
data/src/include/version.h
CHANGED
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
|
|
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
|
|
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
|
|
1171
|
+
hb_array_T* result = hb_array_init(hb_array_size(nodes));
|
|
1172
1172
|
|
|
1173
|
-
for (size_t index = 0; index < nodes
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
}
|