@herb-tools/node 0.8.9 → 0.9.0
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.
- package/CHANGELOG.md +19 -0
- package/binding.gyp +26 -8
- package/dist/herb-node.cjs +41 -12
- package/dist/herb-node.cjs.map +1 -1
- package/dist/herb-node.esm.js +8 -1
- package/dist/herb-node.esm.js.map +1 -1
- package/dist/types/node-backend.d.ts +3 -1
- package/extension/error_helpers.cpp +419 -71
- package/extension/error_helpers.h +14 -3
- package/extension/extension_helpers.cpp +38 -35
- package/extension/extension_helpers.h +2 -2
- package/extension/herb.cpp +183 -64
- package/extension/libherb/analyze/action_view/attribute_extraction_helpers.c +290 -0
- package/extension/libherb/analyze/action_view/attribute_extraction_helpers.h +36 -0
- package/extension/libherb/analyze/action_view/content_tag.c +70 -0
- package/extension/libherb/analyze/action_view/link_to.c +143 -0
- package/extension/libherb/analyze/action_view/registry.c +60 -0
- package/extension/libherb/analyze/action_view/tag.c +64 -0
- package/extension/libherb/analyze/action_view/tag_helper_handler.h +41 -0
- package/extension/libherb/analyze/action_view/tag_helper_node_builders.c +305 -0
- package/extension/libherb/analyze/action_view/tag_helper_node_builders.h +70 -0
- package/extension/libherb/analyze/action_view/tag_helpers.c +748 -0
- package/extension/libherb/analyze/action_view/tag_helpers.h +38 -0
- package/extension/libherb/analyze/action_view/turbo_frame_tag.c +88 -0
- package/extension/libherb/analyze/analyze.c +882 -0
- package/extension/libherb/{include → analyze}/analyze.h +14 -4
- package/extension/libherb/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
- package/extension/libherb/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
- package/extension/libherb/analyze/builders.c +343 -0
- package/extension/libherb/analyze/builders.h +27 -0
- package/extension/libherb/analyze/conditional_elements.c +594 -0
- package/extension/libherb/analyze/conditional_elements.h +9 -0
- package/extension/libherb/analyze/conditional_open_tags.c +640 -0
- package/extension/libherb/analyze/conditional_open_tags.h +9 -0
- package/extension/libherb/analyze/control_type.c +250 -0
- package/extension/libherb/analyze/control_type.h +14 -0
- package/extension/libherb/{analyze_helpers.c → analyze/helpers.c} +79 -31
- package/extension/libherb/{analyze_helpers.h → analyze/helpers.h} +22 -17
- package/extension/libherb/analyze/invalid_structures.c +193 -0
- package/extension/libherb/analyze/invalid_structures.h +11 -0
- package/extension/libherb/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
- package/extension/libherb/analyze/parse_errors.c +84 -0
- package/extension/libherb/analyze/prism_annotate.c +397 -0
- package/extension/libherb/analyze/prism_annotate.h +16 -0
- package/extension/libherb/{analyze_transform.c → analyze/transform.c} +17 -3
- package/extension/libherb/ast_node.c +17 -7
- package/extension/libherb/ast_node.h +11 -5
- package/extension/libherb/ast_nodes.c +663 -388
- package/extension/libherb/ast_nodes.h +118 -39
- package/extension/libherb/ast_pretty_print.c +191 -7
- package/extension/libherb/ast_pretty_print.h +6 -1
- package/extension/libherb/element_source.h +3 -8
- package/extension/libherb/errors.c +1100 -507
- package/extension/libherb/errors.h +155 -54
- package/extension/libherb/extract.c +148 -49
- package/extension/libherb/extract.h +21 -5
- package/extension/libherb/herb.c +52 -34
- package/extension/libherb/herb.h +18 -6
- package/extension/libherb/herb_prism_node.h +13 -0
- package/extension/libherb/html_util.c +241 -12
- package/extension/libherb/html_util.h +7 -2
- package/extension/libherb/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
- package/extension/libherb/include/analyze/action_view/tag_helper_handler.h +41 -0
- package/extension/libherb/include/analyze/action_view/tag_helper_node_builders.h +70 -0
- package/extension/libherb/include/analyze/action_view/tag_helpers.h +38 -0
- package/extension/libherb/{analyze.h → include/analyze/analyze.h} +14 -4
- package/extension/libherb/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
- package/extension/libherb/include/analyze/builders.h +27 -0
- package/extension/libherb/include/analyze/conditional_elements.h +9 -0
- package/extension/libherb/include/analyze/conditional_open_tags.h +9 -0
- package/extension/libherb/include/analyze/control_type.h +14 -0
- package/extension/libherb/include/{analyze_helpers.h → analyze/helpers.h} +22 -17
- package/extension/libherb/include/analyze/invalid_structures.h +11 -0
- package/extension/libherb/include/analyze/prism_annotate.h +16 -0
- package/extension/libherb/include/ast_node.h +11 -5
- package/extension/libherb/include/ast_nodes.h +118 -39
- package/extension/libherb/include/ast_pretty_print.h +6 -1
- package/extension/libherb/include/element_source.h +3 -8
- package/extension/libherb/include/errors.h +155 -54
- package/extension/libherb/include/extract.h +21 -5
- package/extension/libherb/include/herb.h +18 -6
- package/extension/libherb/include/herb_prism_node.h +13 -0
- package/extension/libherb/include/html_util.h +7 -2
- package/extension/libherb/include/io.h +3 -1
- package/extension/libherb/include/lex_helpers.h +29 -0
- package/extension/libherb/include/lexer.h +1 -1
- package/extension/libherb/include/lexer_peek_helpers.h +87 -13
- package/extension/libherb/include/lexer_struct.h +2 -0
- package/extension/libherb/include/location.h +2 -1
- package/extension/libherb/include/parser.h +27 -2
- package/extension/libherb/include/parser_helpers.h +19 -3
- package/extension/libherb/include/pretty_print.h +10 -5
- package/extension/libherb/include/prism_context.h +45 -0
- package/extension/libherb/include/prism_helpers.h +10 -7
- package/extension/libherb/include/prism_serialized.h +12 -0
- package/extension/libherb/include/token.h +16 -4
- package/extension/libherb/include/token_struct.h +10 -3
- package/extension/libherb/include/utf8.h +2 -1
- package/extension/libherb/include/util/hb_allocator.h +78 -0
- package/extension/libherb/include/util/hb_arena.h +6 -1
- package/extension/libherb/include/util/hb_arena_debug.h +12 -1
- package/extension/libherb/include/util/hb_array.h +7 -3
- package/extension/libherb/include/util/hb_buffer.h +6 -4
- package/extension/libherb/include/util/hb_foreach.h +79 -0
- package/extension/libherb/include/util/hb_narray.h +8 -4
- package/extension/libherb/include/util/hb_string.h +56 -9
- package/extension/libherb/include/util/string.h +11 -0
- package/extension/libherb/include/util.h +6 -3
- package/extension/libherb/include/version.h +1 -1
- package/extension/libherb/io.c +3 -2
- package/extension/libherb/io.h +3 -1
- package/extension/libherb/lex_helpers.h +29 -0
- package/extension/libherb/lexer.c +42 -30
- package/extension/libherb/lexer.h +1 -1
- package/extension/libherb/lexer_peek_helpers.c +12 -74
- package/extension/libherb/lexer_peek_helpers.h +87 -13
- package/extension/libherb/lexer_struct.h +2 -0
- package/extension/libherb/location.c +2 -2
- package/extension/libherb/location.h +2 -1
- package/extension/libherb/main.c +79 -66
- package/extension/libherb/parser.c +784 -247
- package/extension/libherb/parser.h +27 -2
- package/extension/libherb/parser_helpers.c +110 -23
- package/extension/libherb/parser_helpers.h +19 -3
- package/extension/libherb/parser_match_tags.c +110 -49
- package/extension/libherb/pretty_print.c +29 -24
- package/extension/libherb/pretty_print.h +10 -5
- package/extension/libherb/prism_context.h +45 -0
- package/extension/libherb/prism_helpers.c +30 -27
- package/extension/libherb/prism_helpers.h +10 -7
- package/extension/libherb/prism_serialized.h +12 -0
- package/extension/libherb/ruby_parser.c +2 -0
- package/extension/libherb/token.c +151 -66
- package/extension/libherb/token.h +16 -4
- package/extension/libherb/token_matchers.c +0 -1
- package/extension/libherb/token_struct.h +10 -3
- package/extension/libherb/utf8.c +7 -6
- package/extension/libherb/utf8.h +2 -1
- package/extension/libherb/util/hb_allocator.c +341 -0
- package/extension/libherb/util/hb_allocator.h +78 -0
- package/extension/libherb/util/hb_arena.c +81 -56
- package/extension/libherb/util/hb_arena.h +6 -1
- package/extension/libherb/util/hb_arena_debug.c +32 -17
- package/extension/libherb/util/hb_arena_debug.h +12 -1
- package/extension/libherb/util/hb_array.c +30 -15
- package/extension/libherb/util/hb_array.h +7 -3
- package/extension/libherb/util/hb_buffer.c +17 -21
- package/extension/libherb/util/hb_buffer.h +6 -4
- package/extension/libherb/util/hb_foreach.h +79 -0
- package/extension/libherb/util/hb_narray.c +22 -7
- package/extension/libherb/util/hb_narray.h +8 -4
- package/extension/libherb/util/hb_string.c +49 -35
- package/extension/libherb/util/hb_string.h +56 -9
- package/extension/libherb/util/string.h +11 -0
- package/extension/libherb/util.c +21 -11
- package/extension/libherb/util.h +6 -3
- package/extension/libherb/version.h +1 -1
- package/extension/libherb/visitor.c +48 -1
- package/extension/nodes.cpp +451 -6
- package/extension/nodes.h +8 -1
- package/extension/prism/include/prism/ast.h +4 -4
- package/extension/prism/include/prism/version.h +2 -2
- package/extension/prism/src/prism.c +1 -1
- package/package.json +12 -8
- package/src/node-backend.ts +11 -1
- package/dist/types/index-cjs.d.cts +0 -1
- package/extension/libherb/analyze.c +0 -1594
- package/extension/libherb/element_source.c +0 -12
- package/extension/libherb/include/util/hb_system.h +0 -9
- package/extension/libherb/util/hb_system.c +0 -30
- package/extension/libherb/util/hb_system.h +0 -9
- package/src/index-cjs.cts +0 -22
- /package/dist/types/{index-esm.d.mts → index.d.ts} +0 -0
- /package/src/{index-esm.mts → index.ts} +0 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#include "../include/analyze/invalid_structures.h"
|
|
2
|
+
#include "../include/analyze/analyze.h"
|
|
3
|
+
#include "../include/analyze/analyzed_ruby.h"
|
|
4
|
+
#include "../include/analyze/helpers.h"
|
|
5
|
+
#include "../include/ast_node.h"
|
|
6
|
+
#include "../include/ast_nodes.h"
|
|
7
|
+
#include "../include/errors.h"
|
|
8
|
+
#include "../include/token_struct.h"
|
|
9
|
+
#include "../include/util/hb_array.h"
|
|
10
|
+
#include "../include/util/hb_string.h"
|
|
11
|
+
#include "../include/visitor.h"
|
|
12
|
+
|
|
13
|
+
#include <stdbool.h>
|
|
14
|
+
#include <stddef.h>
|
|
15
|
+
|
|
16
|
+
bool detect_invalid_erb_structures(const AST_NODE_T* node, void* data) {
|
|
17
|
+
invalid_erb_context_T* context = (invalid_erb_context_T*) data;
|
|
18
|
+
|
|
19
|
+
if (node->type == AST_HTML_ATTRIBUTE_NAME_NODE) { return false; }
|
|
20
|
+
|
|
21
|
+
bool is_begin_node = (node->type == AST_ERB_BEGIN_NODE);
|
|
22
|
+
bool is_loop_node =
|
|
23
|
+
(node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE || node->type == AST_ERB_FOR_NODE
|
|
24
|
+
|| node->type == AST_ERB_BLOCK_NODE);
|
|
25
|
+
|
|
26
|
+
if (is_loop_node) { context->loop_depth++; }
|
|
27
|
+
if (is_begin_node) { context->rescue_depth++; }
|
|
28
|
+
|
|
29
|
+
if (node->type == AST_ERB_CONTENT_NODE) {
|
|
30
|
+
const AST_ERB_CONTENT_NODE_T* content_node = (const AST_ERB_CONTENT_NODE_T*) node;
|
|
31
|
+
|
|
32
|
+
if (content_node->parsed && !content_node->valid && content_node->analyzed_ruby != NULL) {
|
|
33
|
+
analyzed_ruby_T* analyzed = content_node->analyzed_ruby;
|
|
34
|
+
|
|
35
|
+
// =begin
|
|
36
|
+
if (has_error_message(analyzed, "embedded document meets end of file")) {
|
|
37
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
38
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
39
|
+
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// =end
|
|
44
|
+
if (has_error_message(analyzed, "unexpected '=', ignoring it")
|
|
45
|
+
&& has_error_message(analyzed, "unexpected 'end', ignoring it")) {
|
|
46
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
47
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
hb_string_T keyword = HB_STRING_NULL;
|
|
53
|
+
|
|
54
|
+
if (context->loop_depth == 0) {
|
|
55
|
+
if (has_error_message(analyzed, "Invalid break")) {
|
|
56
|
+
keyword = hb_string("`<% break %>`");
|
|
57
|
+
} else if (has_error_message(analyzed, "Invalid next")) {
|
|
58
|
+
keyword = hb_string("`<% next %>`");
|
|
59
|
+
} else if (has_error_message(analyzed, "Invalid redo")) {
|
|
60
|
+
keyword = hb_string("`<% redo %>`");
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
if (has_error_message(analyzed, "Invalid redo") || has_error_message(analyzed, "Invalid break")
|
|
64
|
+
|| has_error_message(analyzed, "Invalid next")) {
|
|
65
|
+
|
|
66
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
67
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
68
|
+
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (context->rescue_depth == 0) {
|
|
74
|
+
if (has_error_message(analyzed, "Invalid retry without rescue")) { keyword = hb_string("`<% retry %>`"); }
|
|
75
|
+
} else {
|
|
76
|
+
if (has_error_message(analyzed, "Invalid retry without rescue")) {
|
|
77
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
78
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
79
|
+
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (hb_string_is_null(keyword)) { keyword = erb_keyword_from_analyzed_ruby(analyzed); }
|
|
85
|
+
|
|
86
|
+
if (!hb_string_is_null(keyword) && !token_value_empty(content_node->tag_closing)) {
|
|
87
|
+
append_erb_control_flow_scope_error(
|
|
88
|
+
keyword,
|
|
89
|
+
node->location.start,
|
|
90
|
+
node->location.end,
|
|
91
|
+
context->allocator,
|
|
92
|
+
node->errors
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (node->type == AST_ERB_IF_NODE) {
|
|
99
|
+
const AST_ERB_IF_NODE_T* if_node = (const AST_ERB_IF_NODE_T*) node;
|
|
100
|
+
|
|
101
|
+
if (if_node->end_node == NULL) { check_erb_node_for_missing_end(node, context->allocator); }
|
|
102
|
+
|
|
103
|
+
if (if_node->statements != NULL) {
|
|
104
|
+
for (size_t i = 0; i < hb_array_size(if_node->statements); i++) {
|
|
105
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(if_node->statements, i);
|
|
106
|
+
|
|
107
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
AST_NODE_T* subsequent = if_node->subsequent;
|
|
112
|
+
|
|
113
|
+
while (subsequent != NULL) {
|
|
114
|
+
if (subsequent->type == AST_ERB_CONTENT_NODE) {
|
|
115
|
+
const AST_ERB_CONTENT_NODE_T* content_node = (const AST_ERB_CONTENT_NODE_T*) subsequent;
|
|
116
|
+
|
|
117
|
+
if (content_node->parsed && !content_node->valid && content_node->analyzed_ruby != NULL) {
|
|
118
|
+
analyzed_ruby_T* analyzed = content_node->analyzed_ruby;
|
|
119
|
+
hb_string_T keyword = erb_keyword_from_analyzed_ruby(analyzed);
|
|
120
|
+
|
|
121
|
+
if (!token_value_empty(content_node->tag_closing)) {
|
|
122
|
+
append_erb_control_flow_scope_error(
|
|
123
|
+
keyword,
|
|
124
|
+
subsequent->location.start,
|
|
125
|
+
subsequent->location.end,
|
|
126
|
+
context->allocator,
|
|
127
|
+
subsequent->errors
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (subsequent->type == AST_ERB_IF_NODE) {
|
|
134
|
+
const AST_ERB_IF_NODE_T* elsif_node = (const AST_ERB_IF_NODE_T*) subsequent;
|
|
135
|
+
|
|
136
|
+
if (elsif_node->statements != NULL) {
|
|
137
|
+
for (size_t i = 0; i < hb_array_size(elsif_node->statements); i++) {
|
|
138
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(elsif_node->statements, i);
|
|
139
|
+
|
|
140
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
subsequent = elsif_node->subsequent;
|
|
145
|
+
} else if (subsequent->type == AST_ERB_ELSE_NODE) {
|
|
146
|
+
const AST_ERB_ELSE_NODE_T* else_node = (const AST_ERB_ELSE_NODE_T*) subsequent;
|
|
147
|
+
|
|
148
|
+
if (else_node->statements != NULL) {
|
|
149
|
+
for (size_t i = 0; i < hb_array_size(else_node->statements); i++) {
|
|
150
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(else_node->statements, i);
|
|
151
|
+
|
|
152
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
break;
|
|
157
|
+
} else {
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (node->type == AST_ERB_UNLESS_NODE || node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE
|
|
164
|
+
|| node->type == AST_ERB_FOR_NODE || node->type == AST_ERB_CASE_NODE || node->type == AST_ERB_CASE_MATCH_NODE
|
|
165
|
+
|| node->type == AST_ERB_BEGIN_NODE || node->type == AST_ERB_BLOCK_NODE || node->type == AST_ERB_ELSE_NODE) {
|
|
166
|
+
herb_visit_child_nodes(node, detect_invalid_erb_structures, context);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (node->type == AST_ERB_UNLESS_NODE || node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE
|
|
170
|
+
|| node->type == AST_ERB_FOR_NODE || node->type == AST_ERB_CASE_NODE || node->type == AST_ERB_CASE_MATCH_NODE
|
|
171
|
+
|| node->type == AST_ERB_BEGIN_NODE || node->type == AST_ERB_BLOCK_NODE || node->type == AST_ERB_ELSE_NODE) {
|
|
172
|
+
check_erb_node_for_missing_end(node, context->allocator);
|
|
173
|
+
|
|
174
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
175
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
176
|
+
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (node->type == AST_ERB_IF_NODE) {
|
|
181
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
182
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
183
|
+
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
bool result = true;
|
|
188
|
+
|
|
189
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
190
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
191
|
+
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
2
|
-
// be modified manually. See /Users/marcoroth/Development/herb-release-0.
|
|
2
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.9.0/templates/src/analyze/missing_end.c.erb
|
|
3
3
|
|
|
4
|
-
#include "include/
|
|
5
|
-
#include "include/errors.h"
|
|
4
|
+
#include "../include/analyze/helpers.h"
|
|
5
|
+
#include "../include/errors.h"
|
|
6
|
+
#include "../include/util/hb_allocator.h"
|
|
7
|
+
#include "../include/util/hb_string.h"
|
|
6
8
|
|
|
7
9
|
|
|
8
|
-
void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
10
|
+
void check_erb_node_for_missing_end(const AST_NODE_T* node, hb_allocator_T* allocator) {
|
|
9
11
|
switch (node->type) {
|
|
10
12
|
case AST_ERB_IF_NODE: {
|
|
11
13
|
const AST_ERB_IF_NODE_T* erb_if_node = (const AST_ERB_IF_NODE_T*) node;
|
|
12
14
|
|
|
13
15
|
if (erb_if_node->end_node == NULL) {
|
|
14
|
-
|
|
15
|
-
"`<" "%" " if " "%" ">`",
|
|
16
|
+
append_missing_erb_end_tag_error(
|
|
17
|
+
hb_string("`<" "%" " if " "%" ">`"),
|
|
16
18
|
erb_if_node->tag_opening->location.start,
|
|
17
19
|
erb_if_node->tag_closing->location.end,
|
|
20
|
+
allocator,
|
|
18
21
|
node->errors
|
|
19
22
|
);
|
|
20
23
|
}
|
|
@@ -26,10 +29,11 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
|
26
29
|
const AST_ERB_BLOCK_NODE_T* erb_block_node = (const AST_ERB_BLOCK_NODE_T*) node;
|
|
27
30
|
|
|
28
31
|
if (erb_block_node->end_node == NULL) {
|
|
29
|
-
|
|
30
|
-
"ERB block",
|
|
32
|
+
append_missing_erb_end_tag_error(
|
|
33
|
+
hb_string("ERB block"),
|
|
31
34
|
erb_block_node->tag_opening->location.start,
|
|
32
35
|
erb_block_node->tag_closing->location.end,
|
|
36
|
+
allocator,
|
|
33
37
|
node->errors
|
|
34
38
|
);
|
|
35
39
|
}
|
|
@@ -41,10 +45,11 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
|
41
45
|
const AST_ERB_CASE_NODE_T* erb_case_node = (const AST_ERB_CASE_NODE_T*) node;
|
|
42
46
|
|
|
43
47
|
if (erb_case_node->end_node == NULL) {
|
|
44
|
-
|
|
45
|
-
"`<" "%" " case " "%" ">`",
|
|
48
|
+
append_missing_erb_end_tag_error(
|
|
49
|
+
hb_string("`<" "%" " case " "%" ">`"),
|
|
46
50
|
erb_case_node->tag_opening->location.start,
|
|
47
51
|
erb_case_node->tag_closing->location.end,
|
|
52
|
+
allocator,
|
|
48
53
|
node->errors
|
|
49
54
|
);
|
|
50
55
|
}
|
|
@@ -56,10 +61,11 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
|
56
61
|
const AST_ERB_CASE_MATCH_NODE_T* erb_case_match_node = (const AST_ERB_CASE_MATCH_NODE_T*) node;
|
|
57
62
|
|
|
58
63
|
if (erb_case_match_node->end_node == NULL) {
|
|
59
|
-
|
|
60
|
-
"`<" "%" " case " "%" ">`",
|
|
64
|
+
append_missing_erb_end_tag_error(
|
|
65
|
+
hb_string("`<" "%" " case " "%" ">`"),
|
|
61
66
|
erb_case_match_node->tag_opening->location.start,
|
|
62
67
|
erb_case_match_node->tag_closing->location.end,
|
|
68
|
+
allocator,
|
|
63
69
|
node->errors
|
|
64
70
|
);
|
|
65
71
|
}
|
|
@@ -71,10 +77,11 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
|
71
77
|
const AST_ERB_WHILE_NODE_T* erb_while_node = (const AST_ERB_WHILE_NODE_T*) node;
|
|
72
78
|
|
|
73
79
|
if (erb_while_node->end_node == NULL) {
|
|
74
|
-
|
|
75
|
-
"`<" "%" " while " "%" ">`",
|
|
80
|
+
append_missing_erb_end_tag_error(
|
|
81
|
+
hb_string("`<" "%" " while " "%" ">`"),
|
|
76
82
|
erb_while_node->tag_opening->location.start,
|
|
77
83
|
erb_while_node->tag_closing->location.end,
|
|
84
|
+
allocator,
|
|
78
85
|
node->errors
|
|
79
86
|
);
|
|
80
87
|
}
|
|
@@ -86,10 +93,11 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
|
86
93
|
const AST_ERB_UNTIL_NODE_T* erb_until_node = (const AST_ERB_UNTIL_NODE_T*) node;
|
|
87
94
|
|
|
88
95
|
if (erb_until_node->end_node == NULL) {
|
|
89
|
-
|
|
90
|
-
"`<" "%" " until " "%" ">`",
|
|
96
|
+
append_missing_erb_end_tag_error(
|
|
97
|
+
hb_string("`<" "%" " until " "%" ">`"),
|
|
91
98
|
erb_until_node->tag_opening->location.start,
|
|
92
99
|
erb_until_node->tag_closing->location.end,
|
|
100
|
+
allocator,
|
|
93
101
|
node->errors
|
|
94
102
|
);
|
|
95
103
|
}
|
|
@@ -101,10 +109,11 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
|
101
109
|
const AST_ERB_FOR_NODE_T* erb_for_node = (const AST_ERB_FOR_NODE_T*) node;
|
|
102
110
|
|
|
103
111
|
if (erb_for_node->end_node == NULL) {
|
|
104
|
-
|
|
105
|
-
"`<" "%" " for " "%" ">`",
|
|
112
|
+
append_missing_erb_end_tag_error(
|
|
113
|
+
hb_string("`<" "%" " for " "%" ">`"),
|
|
106
114
|
erb_for_node->tag_opening->location.start,
|
|
107
115
|
erb_for_node->tag_closing->location.end,
|
|
116
|
+
allocator,
|
|
108
117
|
node->errors
|
|
109
118
|
);
|
|
110
119
|
}
|
|
@@ -116,10 +125,11 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
|
116
125
|
const AST_ERB_BEGIN_NODE_T* erb_begin_node = (const AST_ERB_BEGIN_NODE_T*) node;
|
|
117
126
|
|
|
118
127
|
if (erb_begin_node->end_node == NULL) {
|
|
119
|
-
|
|
120
|
-
"`<" "%" " begin " "%" ">`",
|
|
128
|
+
append_missing_erb_end_tag_error(
|
|
129
|
+
hb_string("`<" "%" " begin " "%" ">`"),
|
|
121
130
|
erb_begin_node->tag_opening->location.start,
|
|
122
131
|
erb_begin_node->tag_closing->location.end,
|
|
132
|
+
allocator,
|
|
123
133
|
node->errors
|
|
124
134
|
);
|
|
125
135
|
}
|
|
@@ -131,10 +141,11 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
|
|
|
131
141
|
const AST_ERB_UNLESS_NODE_T* erb_unless_node = (const AST_ERB_UNLESS_NODE_T*) node;
|
|
132
142
|
|
|
133
143
|
if (erb_unless_node->end_node == NULL) {
|
|
134
|
-
|
|
135
|
-
"`<" "%" " unless " "%" ">`",
|
|
144
|
+
append_missing_erb_end_tag_error(
|
|
145
|
+
hb_string("`<" "%" " unless " "%" ">`"),
|
|
136
146
|
erb_unless_node->tag_opening->location.start,
|
|
137
147
|
erb_unless_node->tag_closing->location.end,
|
|
148
|
+
allocator,
|
|
138
149
|
node->errors
|
|
139
150
|
);
|
|
140
151
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#include "../include/analyze/analyze.h"
|
|
2
|
+
#include "../include/ast_node.h"
|
|
3
|
+
#include "../include/ast_nodes.h"
|
|
4
|
+
#include "../include/errors.h"
|
|
5
|
+
#include "../include/extract.h"
|
|
6
|
+
#include "../include/prism_helpers.h"
|
|
7
|
+
#include "../include/util/hb_allocator.h"
|
|
8
|
+
#include "../include/util/hb_string.h"
|
|
9
|
+
|
|
10
|
+
#include <prism.h>
|
|
11
|
+
#include <stdlib.h>
|
|
12
|
+
#include <string.h>
|
|
13
|
+
|
|
14
|
+
static void parse_erb_content_errors(AST_NODE_T* erb_node, const char* source, hb_allocator_T* allocator) {
|
|
15
|
+
if (!erb_node || erb_node->type != AST_ERB_CONTENT_NODE) { return; }
|
|
16
|
+
AST_ERB_CONTENT_NODE_T* content_node = (AST_ERB_CONTENT_NODE_T*) erb_node;
|
|
17
|
+
|
|
18
|
+
if (!content_node->content || hb_string_is_empty(content_node->content->value)) { return; }
|
|
19
|
+
|
|
20
|
+
char* content = hb_string_to_c_string_using_malloc(content_node->content->value);
|
|
21
|
+
if (!content) { return; }
|
|
22
|
+
|
|
23
|
+
pm_parser_t parser;
|
|
24
|
+
pm_options_t options = { 0, .partial_script = true };
|
|
25
|
+
pm_parser_init(&parser, (const uint8_t*) content, strlen(content), &options);
|
|
26
|
+
|
|
27
|
+
pm_node_t* root = pm_parse(&parser);
|
|
28
|
+
|
|
29
|
+
const pm_diagnostic_t* error = (const pm_diagnostic_t*) parser.error_list.head;
|
|
30
|
+
|
|
31
|
+
if (error != NULL) {
|
|
32
|
+
RUBY_PARSE_ERROR_T* parse_error = ruby_parse_error_from_prism_error_with_positions(
|
|
33
|
+
error,
|
|
34
|
+
erb_node->location.start,
|
|
35
|
+
erb_node->location.end,
|
|
36
|
+
allocator
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
hb_array_append(erb_node->errors, parse_error);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pm_node_destroy(&parser, root);
|
|
43
|
+
pm_parser_free(&parser);
|
|
44
|
+
pm_options_free(&options);
|
|
45
|
+
free(content);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source, hb_allocator_T* allocator) {
|
|
49
|
+
char* extracted_ruby = herb_extract_ruby_with_semicolons(source, allocator);
|
|
50
|
+
|
|
51
|
+
if (!extracted_ruby) { return; }
|
|
52
|
+
|
|
53
|
+
pm_parser_t parser;
|
|
54
|
+
pm_options_t options = { 0, .partial_script = true };
|
|
55
|
+
pm_parser_init(&parser, (const uint8_t*) extracted_ruby, strlen(extracted_ruby), &options);
|
|
56
|
+
|
|
57
|
+
pm_node_t* root = pm_parse(&parser);
|
|
58
|
+
|
|
59
|
+
for (const pm_diagnostic_t* error = (const pm_diagnostic_t*) parser.error_list.head; error != NULL;
|
|
60
|
+
error = (const pm_diagnostic_t*) error->node.next) {
|
|
61
|
+
size_t error_offset = (size_t) (error->location.start - parser.start);
|
|
62
|
+
|
|
63
|
+
if (strstr(error->message, "unexpected ';'") != NULL) {
|
|
64
|
+
if (error_offset < strlen(extracted_ruby) && extracted_ruby[error_offset] == ';') {
|
|
65
|
+
if (error_offset >= strlen(source) || source[error_offset] != ';') {
|
|
66
|
+
AST_NODE_T* erb_node = find_erb_content_at_offset(document, source, error_offset);
|
|
67
|
+
|
|
68
|
+
if (erb_node) { parse_erb_content_errors(erb_node, source, allocator); }
|
|
69
|
+
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
RUBY_PARSE_ERROR_T* parse_error =
|
|
76
|
+
ruby_parse_error_from_prism_error(error, (AST_NODE_T*) document, source, &parser, allocator);
|
|
77
|
+
hb_array_append(document->base.errors, parse_error);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
pm_node_destroy(&parser, root);
|
|
81
|
+
pm_parser_free(&parser);
|
|
82
|
+
pm_options_free(&options);
|
|
83
|
+
hb_allocator_dealloc(allocator, extracted_ruby);
|
|
84
|
+
}
|