herb 0.8.3-arm64-darwin → 0.8.5-arm64-darwin
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/config.yml +7 -0
- data/ext/herb/error_helpers.c +26 -1
- data/ext/herb/extension_helpers.c +1 -1
- data/ext/herb/nodes.c +2 -2
- data/lib/herb/3.0/herb.bundle +0 -0
- data/lib/herb/3.1/herb.bundle +0 -0
- data/lib/herb/3.2/herb.bundle +0 -0
- data/lib/herb/3.3/herb.bundle +0 -0
- data/lib/herb/3.4/herb.bundle +0 -0
- data/lib/herb/ast/helpers.rb +5 -0
- data/lib/herb/engine/compiler.rb +1 -0
- data/lib/herb/engine/debug_visitor.rb +24 -1
- data/lib/herb/errors.rb +53 -44
- data/lib/herb/version.rb +1 -1
- data/sig/herb/ast/helpers.rbs +3 -0
- data/sig/herb/engine/debug_visitor.rbs +5 -0
- data/sig/herb/errors.rbs +10 -0
- data/sig/serialized_ast_errors.rbs +3 -0
- data/src/analyze.c +39 -28
- data/src/analyze_helpers.c +179 -84
- data/src/analyzed_ruby.c +26 -25
- data/src/ast_node.c +1 -1
- data/src/ast_nodes.c +157 -53
- data/src/ast_pretty_print.c +16 -15
- data/src/errors.c +42 -5
- data/src/extract.c +4 -3
- data/src/herb.c +2 -2
- data/src/include/analyze_helpers.h +1 -0
- data/src/include/analyzed_ruby.h +19 -18
- data/src/include/errors.h +8 -0
- data/src/include/version.h +1 -1
- data/src/lexer.c +3 -3
- data/src/parser.c +10 -8
- data/src/parser_helpers.c +9 -9
- data/src/pretty_print.c +6 -6
- data/src/visitor.c +26 -26
- data/templates/ext/herb/error_helpers.c.erb +1 -1
- data/templates/ext/herb/nodes.c.erb +1 -1
- data/templates/java/error_helpers.c.erb +1 -1
- data/templates/java/nodes.c.erb +2 -2
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +1 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +1 -1
- data/templates/lib/herb/errors.rb.erb +8 -5
- data/templates/rust/src/ast/nodes.rs.erb +2 -2
- data/templates/src/ast_nodes.c.erb +7 -3
- data/templates/src/ast_pretty_print.c.erb +16 -15
- data/templates/src/errors.c.erb +5 -5
- data/templates/src/visitor.c.erb +1 -1
- data/templates/wasm/error_helpers.cpp.erb +1 -1
- data/templates/wasm/nodes.cpp.erb +1 -1
- metadata +1 -1
data/src/errors.c
CHANGED
|
@@ -497,6 +497,20 @@ void append_missingerb_end_tag_error(const char* keyword, position_T start, posi
|
|
|
497
497
|
hb_array_append(errors, missingerb_end_tag_error_init(keyword, start, end));
|
|
498
498
|
}
|
|
499
499
|
|
|
500
|
+
ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T* erb_multiple_blocks_in_tag_error_init(position_T start, position_T end) {
|
|
501
|
+
ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T* erb_multiple_blocks_in_tag_error = malloc(sizeof(ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T));
|
|
502
|
+
|
|
503
|
+
error_init(&erb_multiple_blocks_in_tag_error->base, ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR, start, end);
|
|
504
|
+
|
|
505
|
+
erb_multiple_blocks_in_tag_error->base.message = herb_strdup("Multiple unclosed control flow blocks in a single ERB tag. Split each block into its own ERB tag, or close all blocks within the same tag.");
|
|
506
|
+
|
|
507
|
+
return erb_multiple_blocks_in_tag_error;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
void append_erb_multiple_blocks_in_tag_error(position_T start, position_T end, hb_array_T* errors) {
|
|
511
|
+
hb_array_append(errors, erb_multiple_blocks_in_tag_error_init(start, end));
|
|
512
|
+
}
|
|
513
|
+
|
|
500
514
|
const char* error_type_to_string(ERROR_T* error) {
|
|
501
515
|
switch (error->type) {
|
|
502
516
|
case UNEXPECTED_ERROR: return "UNEXPECTED_ERROR";
|
|
@@ -510,6 +524,7 @@ const char* error_type_to_string(ERROR_T* error) {
|
|
|
510
524
|
case RUBY_PARSE_ERROR: return "RUBY_PARSE_ERROR";
|
|
511
525
|
case ERB_CONTROL_FLOW_SCOPE_ERROR: return "ERB_CONTROL_FLOW_SCOPE_ERROR";
|
|
512
526
|
case MISSINGERB_END_TAG_ERROR: return "MISSINGERB_END_TAG_ERROR";
|
|
527
|
+
case ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR: return "ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR";
|
|
513
528
|
}
|
|
514
529
|
|
|
515
530
|
return "Unknown error_type_T";
|
|
@@ -528,6 +543,7 @@ const char* error_human_type(ERROR_T* error) {
|
|
|
528
543
|
case RUBY_PARSE_ERROR: return "RubyParseError";
|
|
529
544
|
case ERB_CONTROL_FLOW_SCOPE_ERROR: return "ERBControlFlowScopeError";
|
|
530
545
|
case MISSINGERB_END_TAG_ERROR: return "MissingERBEndTagError";
|
|
546
|
+
case ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR: return "ERBMultipleBlocksInTagError";
|
|
531
547
|
}
|
|
532
548
|
|
|
533
549
|
return "Unknown error_type_T";
|
|
@@ -616,6 +632,12 @@ static void error_free_missingerb_end_tag_error(MISSINGERB_END_TAG_ERROR_T* miss
|
|
|
616
632
|
error_free_base_error(&missingerb_end_tag_error->base);
|
|
617
633
|
}
|
|
618
634
|
|
|
635
|
+
static void error_free_erb_multiple_blocks_in_tag_error(ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T* erb_multiple_blocks_in_tag_error) {
|
|
636
|
+
/* no ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T specific fields to free up */
|
|
637
|
+
|
|
638
|
+
error_free_base_error(&erb_multiple_blocks_in_tag_error->base);
|
|
639
|
+
}
|
|
640
|
+
|
|
619
641
|
void error_free(ERROR_T* error) {
|
|
620
642
|
if (!error) { return; }
|
|
621
643
|
|
|
@@ -631,6 +653,7 @@ void error_free(ERROR_T* error) {
|
|
|
631
653
|
case RUBY_PARSE_ERROR: error_free_ruby_parse_error((RUBY_PARSE_ERROR_T*) error); break;
|
|
632
654
|
case ERB_CONTROL_FLOW_SCOPE_ERROR: error_free_erb_control_flow_scope_error((ERB_CONTROL_FLOW_SCOPE_ERROR_T*) error); break;
|
|
633
655
|
case MISSINGERB_END_TAG_ERROR: error_free_missingerb_end_tag_error((MISSINGERB_END_TAG_ERROR_T*) error); break;
|
|
656
|
+
case ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR: error_free_erb_multiple_blocks_in_tag_error((ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T*) error); break;
|
|
634
657
|
}
|
|
635
658
|
}
|
|
636
659
|
|
|
@@ -644,7 +667,7 @@ void error_pretty_print_array(
|
|
|
644
667
|
return;
|
|
645
668
|
}
|
|
646
669
|
|
|
647
|
-
if (
|
|
670
|
+
if (array->size == 0) {
|
|
648
671
|
pretty_print_property(hb_string(name), hb_string("[]"), indent, relative_indent, last_property, buffer);
|
|
649
672
|
|
|
650
673
|
return;
|
|
@@ -655,17 +678,17 @@ void error_pretty_print_array(
|
|
|
655
678
|
hb_buffer_append(buffer, "(");
|
|
656
679
|
|
|
657
680
|
char count[16];
|
|
658
|
-
sprintf(count, "%zu",
|
|
681
|
+
sprintf(count, "%zu", array->size);
|
|
659
682
|
hb_buffer_append(buffer, count);
|
|
660
683
|
hb_buffer_append(buffer, ")\n");
|
|
661
684
|
|
|
662
685
|
if (indent < 20) {
|
|
663
|
-
for (size_t i = 0; i <
|
|
686
|
+
for (size_t i = 0; i < array->size; i++) {
|
|
664
687
|
ERROR_T* child = hb_array_get(array, i);
|
|
665
688
|
pretty_print_indent(buffer, indent);
|
|
666
689
|
pretty_print_indent(buffer, relative_indent + 1);
|
|
667
690
|
|
|
668
|
-
if (i ==
|
|
691
|
+
if (i == array->size - 1) {
|
|
669
692
|
hb_buffer_append(buffer, "└── ");
|
|
670
693
|
} else {
|
|
671
694
|
hb_buffer_append(buffer, "├── ");
|
|
@@ -673,7 +696,7 @@ void error_pretty_print_array(
|
|
|
673
696
|
|
|
674
697
|
error_pretty_print(child, indent + 1, relative_indent + 1, buffer);
|
|
675
698
|
|
|
676
|
-
if (i !=
|
|
699
|
+
if (i != array->size - 1) { pretty_print_newline(indent + 1, relative_indent, buffer); }
|
|
677
700
|
}
|
|
678
701
|
}
|
|
679
702
|
}
|
|
@@ -841,6 +864,19 @@ static void error_pretty_print_missingerb_end_tag_error(MISSINGERB_END_TAG_ERROR
|
|
|
841
864
|
pretty_print_quoted_property(hb_string("keyword"), hb_string(error->keyword), indent, relative_indent, true, buffer);
|
|
842
865
|
}
|
|
843
866
|
|
|
867
|
+
static void error_pretty_print_erb_multiple_blocks_in_tag_error(ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T* error, const size_t indent, const size_t relative_indent, hb_buffer_T* buffer) {
|
|
868
|
+
if (!error) { return; }
|
|
869
|
+
|
|
870
|
+
hb_buffer_append(buffer, "@ ");
|
|
871
|
+
hb_buffer_append(buffer, error_human_type((ERROR_T*) error));
|
|
872
|
+
hb_buffer_append(buffer, " ");
|
|
873
|
+
|
|
874
|
+
pretty_print_location(error->base.location, buffer);
|
|
875
|
+
hb_buffer_append(buffer, "\n");
|
|
876
|
+
|
|
877
|
+
pretty_print_quoted_property(hb_string("message"), hb_string(error->base.message), indent, relative_indent, true, buffer);
|
|
878
|
+
}
|
|
879
|
+
|
|
844
880
|
void error_pretty_print(ERROR_T* error, const size_t indent, const size_t relative_indent, hb_buffer_T* buffer) {
|
|
845
881
|
if (!error) { return; }
|
|
846
882
|
|
|
@@ -856,5 +892,6 @@ void error_pretty_print(ERROR_T* error, const size_t indent, const size_t relati
|
|
|
856
892
|
case RUBY_PARSE_ERROR: error_pretty_print_ruby_parse_error((RUBY_PARSE_ERROR_T*) error, indent, relative_indent, buffer); break;
|
|
857
893
|
case ERB_CONTROL_FLOW_SCOPE_ERROR: error_pretty_print_erb_control_flow_scope_error((ERB_CONTROL_FLOW_SCOPE_ERROR_T*) error, indent, relative_indent, buffer); break;
|
|
858
894
|
case MISSINGERB_END_TAG_ERROR: error_pretty_print_missingerb_end_tag_error((MISSINGERB_END_TAG_ERROR_T*) error, indent, relative_indent, buffer); break;
|
|
895
|
+
case ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR: error_pretty_print_erb_multiple_blocks_in_tag_error((ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T*) error, indent, relative_indent, buffer); break;
|
|
859
896
|
}
|
|
860
897
|
}
|
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 <
|
|
15
|
+
for (size_t i = 0; i < tokens->size; i++) {
|
|
16
16
|
const token_T* token = hb_array_get(tokens, i);
|
|
17
17
|
|
|
18
18
|
switch (token->type) {
|
|
@@ -25,7 +25,8 @@ void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output) {
|
|
|
25
25
|
if (strcmp(token->value, "<%#") == 0) {
|
|
26
26
|
skip_erb_content = true;
|
|
27
27
|
is_comment_tag = true;
|
|
28
|
-
} else if (strcmp(token->value, "<%%") == 0 || strcmp(token->value, "<%%=") == 0
|
|
28
|
+
} else if (strcmp(token->value, "<%%") == 0 || strcmp(token->value, "<%%=") == 0
|
|
29
|
+
|| strcmp(token->value, "<%graphql") == 0) {
|
|
29
30
|
skip_erb_content = true;
|
|
30
31
|
is_comment_tag = false;
|
|
31
32
|
} else {
|
|
@@ -94,7 +95,7 @@ void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output) {
|
|
|
94
95
|
void herb_extract_html_to_buffer(const char* source, hb_buffer_T* output) {
|
|
95
96
|
hb_array_T* tokens = herb_lex(source);
|
|
96
97
|
|
|
97
|
-
for (size_t i = 0; i <
|
|
98
|
+
for (size_t i = 0; i < tokens->size; i++) {
|
|
98
99
|
const token_T* token = hb_array_get(tokens, i);
|
|
99
100
|
|
|
100
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 <
|
|
61
|
+
for (size_t i = 0; i < tokens->size; 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 <
|
|
77
|
+
for (size_t i = 0; i < (*tokens)->size; i++) {
|
|
78
78
|
token_T* token = hb_array_get(*tokens, i);
|
|
79
79
|
if (token) { token_free(token); }
|
|
80
80
|
}
|
|
@@ -46,6 +46,7 @@ bool search_in_nodes(analyzed_ruby_T* analyzed);
|
|
|
46
46
|
bool search_rescue_nodes(analyzed_ruby_T* analyzed);
|
|
47
47
|
bool search_ensure_nodes(analyzed_ruby_T* analyzed);
|
|
48
48
|
bool search_yield_nodes(const pm_node_t* node, void* data);
|
|
49
|
+
bool search_unclosed_control_flows(const pm_node_t* node, void* data);
|
|
49
50
|
|
|
50
51
|
void check_erb_node_for_missing_end(const AST_NODE_T* node);
|
|
51
52
|
|
data/src/include/analyzed_ruby.h
CHANGED
|
@@ -11,24 +11,25 @@ typedef struct ANALYZED_RUBY_STRUCT {
|
|
|
11
11
|
pm_node_t* root;
|
|
12
12
|
bool valid;
|
|
13
13
|
bool parsed;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
14
|
+
int if_node_count;
|
|
15
|
+
int elsif_node_count;
|
|
16
|
+
int else_node_count;
|
|
17
|
+
int end_count;
|
|
18
|
+
int block_closing_count;
|
|
19
|
+
int block_node_count;
|
|
20
|
+
int case_node_count;
|
|
21
|
+
int case_match_node_count;
|
|
22
|
+
int when_node_count;
|
|
23
|
+
int in_node_count;
|
|
24
|
+
int for_node_count;
|
|
25
|
+
int while_node_count;
|
|
26
|
+
int until_node_count;
|
|
27
|
+
int begin_node_count;
|
|
28
|
+
int rescue_node_count;
|
|
29
|
+
int ensure_node_count;
|
|
30
|
+
int unless_node_count;
|
|
31
|
+
int yield_node_count;
|
|
32
|
+
int unclosed_control_flow_count;
|
|
32
33
|
} analyzed_ruby_T;
|
|
33
34
|
|
|
34
35
|
analyzed_ruby_T* init_analyzed_ruby(hb_string_T source);
|
data/src/include/errors.h
CHANGED
|
@@ -23,6 +23,7 @@ typedef enum {
|
|
|
23
23
|
RUBY_PARSE_ERROR,
|
|
24
24
|
ERB_CONTROL_FLOW_SCOPE_ERROR,
|
|
25
25
|
MISSINGERB_END_TAG_ERROR,
|
|
26
|
+
ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR,
|
|
26
27
|
} error_type_T;
|
|
27
28
|
|
|
28
29
|
typedef struct ERROR_STRUCT {
|
|
@@ -96,6 +97,11 @@ typedef struct {
|
|
|
96
97
|
const char* keyword;
|
|
97
98
|
} MISSINGERB_END_TAG_ERROR_T;
|
|
98
99
|
|
|
100
|
+
typedef struct {
|
|
101
|
+
ERROR_T base;
|
|
102
|
+
/* no additional fields */
|
|
103
|
+
} ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T;
|
|
104
|
+
|
|
99
105
|
UNEXPECTED_ERROR_T* unexpected_error_init(const char* description, const char* expected, const char* found, position_T start, position_T end);
|
|
100
106
|
void append_unexpected_error(const char* description, const char* expected, const char* found, position_T start, position_T end, hb_array_T* errors);
|
|
101
107
|
UNEXPECTED_TOKEN_ERROR_T* unexpected_token_error_init(token_type_T expected_type, token_T* found, position_T start, position_T end);
|
|
@@ -118,6 +124,8 @@ ERB_CONTROL_FLOW_SCOPE_ERROR_T* erb_control_flow_scope_error_init(const char* ke
|
|
|
118
124
|
void append_erb_control_flow_scope_error(const char* keyword, position_T start, position_T end, hb_array_T* errors);
|
|
119
125
|
MISSINGERB_END_TAG_ERROR_T* missingerb_end_tag_error_init(const char* keyword, position_T start, position_T end);
|
|
120
126
|
void append_missingerb_end_tag_error(const char* keyword, position_T start, position_T end, hb_array_T* errors);
|
|
127
|
+
ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR_T* erb_multiple_blocks_in_tag_error_init(position_T start, position_T end);
|
|
128
|
+
void append_erb_multiple_blocks_in_tag_error(position_T start, position_T end, hb_array_T* errors);
|
|
121
129
|
|
|
122
130
|
void error_init(ERROR_T* error, error_type_T type, position_T start, position_T end);
|
|
123
131
|
|
data/src/include/version.h
CHANGED
data/src/lexer.c
CHANGED
|
@@ -185,8 +185,8 @@ static token_T* lexer_parse_identifier(lexer_T* lexer) {
|
|
|
185
185
|
// ===== ERB Parsing
|
|
186
186
|
|
|
187
187
|
static token_T* lexer_parse_erb_open(lexer_T* lexer) {
|
|
188
|
-
hb_string_T erb_patterns[] = { hb_string("<%=="), hb_string("<%%="), hb_string("<%="),
|
|
189
|
-
hb_string("<%-"), hb_string("<%%"), hb_string("<%") };
|
|
188
|
+
hb_string_T erb_patterns[] = { hb_string("<%=="), hb_string("<%%="), hb_string("<%="), hb_string("<%#"),
|
|
189
|
+
hb_string("<%-"), hb_string("<%%"), hb_string("<%graphql"), hb_string("<%") };
|
|
190
190
|
|
|
191
191
|
lexer->state = STATE_ERB_CONTENT;
|
|
192
192
|
|
|
@@ -278,7 +278,7 @@ token_T* lexer_next_token(lexer_T* lexer) {
|
|
|
278
278
|
return lexer_advance_with_next(lexer, strlen("<![CDATA["), TOKEN_CDATA_START);
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
if (
|
|
281
|
+
if (isalpha(lexer_peek(lexer, 1))) { return lexer_advance_current(lexer, TOKEN_HTML_TAG_START); }
|
|
282
282
|
|
|
283
283
|
if (lexer_peek_for_html_comment_start(lexer, 0)) {
|
|
284
284
|
return lexer_advance_with(lexer, hb_string("<!--"), TOKEN_HTML_COMMENT_START);
|
data/src/parser.c
CHANGED
|
@@ -1115,7 +1115,9 @@ static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, h
|
|
|
1115
1115
|
TOKEN_DASH,
|
|
1116
1116
|
TOKEN_EQUALS,
|
|
1117
1117
|
TOKEN_EXCLAMATION,
|
|
1118
|
+
TOKEN_HTML_TAG_END,
|
|
1118
1119
|
TOKEN_IDENTIFIER,
|
|
1120
|
+
TOKEN_LT,
|
|
1119
1121
|
TOKEN_NBSP,
|
|
1120
1122
|
TOKEN_NEWLINE,
|
|
1121
1123
|
TOKEN_PERCENT,
|
|
@@ -1142,18 +1144,18 @@ static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, h
|
|
|
1142
1144
|
static size_t find_matching_close_tag(hb_array_T* nodes, size_t start_idx, hb_string_T tag_name) {
|
|
1143
1145
|
int depth = 0;
|
|
1144
1146
|
|
|
1145
|
-
for (size_t i = start_idx + 1; i <
|
|
1147
|
+
for (size_t i = start_idx + 1; i < nodes->size; i++) {
|
|
1146
1148
|
AST_NODE_T* node = (AST_NODE_T*) hb_array_get(nodes, i);
|
|
1147
1149
|
if (node == NULL) { continue; }
|
|
1148
1150
|
|
|
1149
1151
|
if (node->type == AST_HTML_OPEN_TAG_NODE) {
|
|
1150
1152
|
AST_HTML_OPEN_TAG_NODE_T* open = (AST_HTML_OPEN_TAG_NODE_T*) node;
|
|
1151
1153
|
|
|
1152
|
-
if (
|
|
1154
|
+
if (hb_string_equals_case_insensitive(hb_string(open->tag_name->value), tag_name)) { depth++; }
|
|
1153
1155
|
} else if (node->type == AST_HTML_CLOSE_TAG_NODE) {
|
|
1154
1156
|
AST_HTML_CLOSE_TAG_NODE_T* close = (AST_HTML_CLOSE_TAG_NODE_T*) node;
|
|
1155
1157
|
|
|
1156
|
-
if (
|
|
1158
|
+
if (hb_string_equals_case_insensitive(hb_string(close->tag_name->value), tag_name)) {
|
|
1157
1159
|
if (depth == 0) { return i; }
|
|
1158
1160
|
depth--;
|
|
1159
1161
|
}
|
|
@@ -1166,9 +1168,9 @@ static size_t find_matching_close_tag(hb_array_T* nodes, size_t start_idx, hb_st
|
|
|
1166
1168
|
static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T* errors);
|
|
1167
1169
|
|
|
1168
1170
|
static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T* errors) {
|
|
1169
|
-
hb_array_T* result = hb_array_init(
|
|
1171
|
+
hb_array_T* result = hb_array_init(nodes->size);
|
|
1170
1172
|
|
|
1171
|
-
for (size_t index = 0; index <
|
|
1173
|
+
for (size_t index = 0; index < nodes->size; index++) {
|
|
1172
1174
|
AST_NODE_T* node = (AST_NODE_T*) hb_array_get(nodes, index);
|
|
1173
1175
|
if (node == NULL) { continue; }
|
|
1174
1176
|
|
|
@@ -1179,7 +1181,7 @@ static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T
|
|
|
1179
1181
|
size_t close_index = find_matching_close_tag(nodes, index, tag_name);
|
|
1180
1182
|
|
|
1181
1183
|
if (close_index == (size_t) -1) {
|
|
1182
|
-
if (
|
|
1184
|
+
if (open_tag->base.errors->size == 0) {
|
|
1183
1185
|
append_missing_closing_tag_error(
|
|
1184
1186
|
open_tag->tag_name,
|
|
1185
1187
|
open_tag->base.location.start,
|
|
@@ -1223,7 +1225,7 @@ static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T
|
|
|
1223
1225
|
AST_HTML_CLOSE_TAG_NODE_T* close_tag = (AST_HTML_CLOSE_TAG_NODE_T*) node;
|
|
1224
1226
|
|
|
1225
1227
|
if (!is_void_element(hb_string(close_tag->tag_name->value))) {
|
|
1226
|
-
if (
|
|
1228
|
+
if (close_tag->base.errors->size == 0) {
|
|
1227
1229
|
append_missing_opening_tag_error(
|
|
1228
1230
|
close_tag->tag_name,
|
|
1229
1231
|
close_tag->base.location.start,
|
|
@@ -1297,7 +1299,7 @@ void herb_parser_deinit(parser_T* parser) {
|
|
|
1297
1299
|
}
|
|
1298
1300
|
|
|
1299
1301
|
void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors) {
|
|
1300
|
-
if (nodes == NULL ||
|
|
1302
|
+
if (nodes == NULL || nodes->size == 0) { return; }
|
|
1301
1303
|
|
|
1302
1304
|
hb_array_T* processed = parser_build_elements_from_tags(nodes, errors);
|
|
1303
1305
|
|
data/src/parser_helpers.c
CHANGED
|
@@ -19,16 +19,16 @@ 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 (
|
|
22
|
+
if (parser->open_tags_stack->size == 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; };
|
|
26
26
|
|
|
27
|
-
return
|
|
27
|
+
return hb_string_equals_case_insensitive(hb_string(top_token->value), tag_name);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
token_T* parser_pop_open_tag(const parser_T* parser) {
|
|
31
|
-
if (
|
|
31
|
+
if (parser->open_tags_stack->size == 0) { return NULL; }
|
|
32
32
|
|
|
33
33
|
return hb_array_pop(parser->open_tags_stack);
|
|
34
34
|
}
|
|
@@ -42,14 +42,14 @@ 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 =
|
|
45
|
+
size_t stack_size = parser->open_tags_stack->size;
|
|
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);
|
|
49
49
|
|
|
50
50
|
if (tag && tag->value) {
|
|
51
51
|
hb_string_T tag_value_string = hb_string(tag->value);
|
|
52
|
-
if (
|
|
52
|
+
if (hb_string_equals_case_insensitive(tag_value_string, hb_string("svg"))) { return true; }
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -61,8 +61,8 @@ bool parser_in_svg_context(const parser_T* parser) {
|
|
|
61
61
|
foreign_content_type_T parser_get_foreign_content_type(hb_string_T tag_name) {
|
|
62
62
|
if (hb_string_is_empty(tag_name)) { return FOREIGN_CONTENT_UNKNOWN; }
|
|
63
63
|
|
|
64
|
-
if (
|
|
65
|
-
if (
|
|
64
|
+
if (hb_string_equals_case_insensitive(tag_name, hb_string("script"))) { return FOREIGN_CONTENT_SCRIPT; }
|
|
65
|
+
if (hb_string_equals_case_insensitive(tag_name, hb_string("style"))) { return FOREIGN_CONTENT_STYLE; }
|
|
66
66
|
|
|
67
67
|
return FOREIGN_CONTENT_UNKNOWN;
|
|
68
68
|
}
|
|
@@ -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 (
|
|
194
|
+
if (parser->open_tags_stack->size > 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
|
|
|
@@ -217,5 +217,5 @@ bool parser_is_expected_closing_tag_name(hb_string_T tag_name, foreign_content_t
|
|
|
217
217
|
|
|
218
218
|
if (hb_string_is_empty(tag_name) || hb_string_is_empty(expected_tag_name)) { return false; }
|
|
219
219
|
|
|
220
|
-
return
|
|
220
|
+
return hb_string_equals_case_insensitive(expected_tag_name, tag_name);
|
|
221
221
|
}
|
data/src/pretty_print.c
CHANGED
|
@@ -113,7 +113,7 @@ void pretty_print_array(
|
|
|
113
113
|
return;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
if (
|
|
116
|
+
if (array->size == 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",
|
|
127
|
+
sprintf(count, "%zu", array->size);
|
|
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 <
|
|
132
|
+
for (size_t i = 0; i < array->size; 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 ==
|
|
137
|
+
if (i == array->size - 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 !=
|
|
145
|
+
if (i != array->size - 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 &&
|
|
158
|
+
if (node->errors != NULL && node->errors->size > 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
|
}
|