herb 0.7.5 → 0.8.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.
- checksums.yaml +4 -4
- data/Makefile +8 -5
- data/config.yml +26 -6
- data/ext/herb/error_helpers.c +57 -3
- data/ext/herb/error_helpers.h +1 -1
- data/ext/herb/extconf.rb +1 -0
- data/ext/herb/extension.c +10 -24
- data/ext/herb/extension_helpers.c +3 -3
- data/ext/herb/extension_helpers.h +1 -1
- data/ext/herb/nodes.c +72 -37
- data/herb.gemspec +0 -2
- data/lib/herb/ast/helpers.rb +11 -0
- data/lib/herb/ast/node.rb +15 -6
- data/lib/herb/ast/nodes.rb +609 -392
- data/lib/herb/cli.rb +31 -0
- data/lib/herb/colors.rb +82 -0
- data/lib/herb/engine/compiler.rb +140 -14
- data/lib/herb/engine/debug_visitor.rb +1 -5
- data/lib/herb/engine/parser_error_overlay.rb +1 -1
- data/lib/herb/engine.rb +8 -14
- data/lib/herb/errors.rb +166 -56
- data/lib/herb/location.rb +2 -2
- data/lib/herb/project.rb +86 -21
- data/lib/herb/token.rb +14 -2
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +1 -0
- data/sig/herb/ast/helpers.rbs +3 -0
- data/sig/herb/ast/node.rbs +12 -5
- data/sig/herb/ast/nodes.rbs +124 -62
- data/sig/herb/colors.rbs +35 -0
- data/sig/herb/engine/compiler.rbs +23 -1
- data/sig/herb/errors.rbs +74 -20
- data/sig/herb/token.rbs +8 -0
- data/sig/herb_c_extension.rbs +1 -1
- data/sig/serialized_ast_errors.rbs +8 -0
- data/src/analyze.c +420 -171
- data/src/analyze_helpers.c +5 -0
- data/src/analyze_missing_end.c +147 -0
- data/src/analyze_transform.c +196 -0
- data/src/analyzed_ruby.c +23 -2
- data/src/ast_node.c +5 -5
- data/src/ast_nodes.c +179 -179
- data/src/ast_pretty_print.c +232 -232
- data/src/element_source.c +7 -6
- data/src/errors.c +246 -126
- data/src/extract.c +92 -34
- data/src/herb.c +37 -49
- data/src/html_util.c +34 -96
- data/src/include/analyze.h +10 -2
- data/src/include/analyze_helpers.h +3 -0
- data/src/include/analyzed_ruby.h +4 -2
- data/src/include/ast_node.h +2 -2
- data/src/include/ast_nodes.h +67 -66
- data/src/include/ast_pretty_print.h +2 -2
- data/src/include/element_source.h +3 -1
- data/src/include/errors.h +30 -14
- data/src/include/extract.h +4 -4
- data/src/include/herb.h +6 -7
- data/src/include/html_util.h +4 -5
- data/src/include/lexer.h +1 -3
- data/src/include/lexer_peek_helpers.h +14 -14
- data/src/include/lexer_struct.h +3 -2
- data/src/include/macros.h +4 -0
- data/src/include/parser.h +12 -6
- data/src/include/parser_helpers.h +25 -15
- data/src/include/pretty_print.h +38 -28
- data/src/include/token.h +5 -8
- data/src/include/utf8.h +3 -2
- data/src/include/util/hb_arena.h +31 -0
- data/src/include/util/hb_arena_debug.h +8 -0
- data/src/include/util/hb_array.h +33 -0
- data/src/include/util/hb_buffer.h +34 -0
- data/src/include/util/hb_string.h +29 -0
- data/src/include/util/hb_system.h +9 -0
- data/src/include/util.h +3 -14
- data/src/include/version.h +1 -1
- data/src/include/visitor.h +1 -1
- data/src/io.c +7 -4
- data/src/lexer.c +61 -88
- data/src/lexer_peek_helpers.c +35 -37
- data/src/main.c +19 -23
- data/src/parser.c +282 -201
- data/src/parser_helpers.c +46 -40
- data/src/parser_match_tags.c +316 -0
- data/src/pretty_print.c +82 -106
- data/src/token.c +18 -65
- data/src/utf8.c +4 -4
- data/src/util/hb_arena.c +179 -0
- data/src/util/hb_arena_debug.c +237 -0
- data/src/{array.c → util/hb_array.c} +26 -27
- data/src/util/hb_buffer.c +203 -0
- data/src/util/hb_string.c +85 -0
- data/src/util/hb_system.c +30 -0
- data/src/util.c +29 -99
- data/src/visitor.c +54 -54
- data/templates/ext/herb/error_helpers.c.erb +3 -3
- data/templates/ext/herb/error_helpers.h.erb +1 -1
- data/templates/ext/herb/nodes.c.erb +11 -6
- data/templates/java/error_helpers.c.erb +75 -0
- data/templates/java/error_helpers.h.erb +20 -0
- data/templates/java/nodes.c.erb +97 -0
- data/templates/java/nodes.h.erb +23 -0
- data/templates/java/org/herb/ast/Errors.java.erb +121 -0
- data/templates/java/org/herb/ast/NodeVisitor.java.erb +14 -0
- data/templates/java/org/herb/ast/Nodes.java.erb +220 -0
- data/templates/java/org/herb/ast/Visitor.java.erb +56 -0
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +8 -8
- data/templates/javascript/packages/node/extension/error_helpers.h.erb +1 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +9 -9
- data/templates/javascript/packages/node/extension/nodes.h.erb +1 -1
- data/templates/lib/herb/ast/nodes.rb.erb +28 -16
- data/templates/lib/herb/errors.rb.erb +17 -12
- data/templates/rust/src/ast/nodes.rs.erb +220 -0
- data/templates/rust/src/errors.rs.erb +216 -0
- data/templates/rust/src/nodes.rs.erb +374 -0
- data/templates/src/analyze_missing_end.c.erb +36 -0
- data/templates/src/analyze_transform.c.erb +24 -0
- data/templates/src/ast_nodes.c.erb +14 -14
- data/templates/src/ast_pretty_print.c.erb +36 -36
- data/templates/src/errors.c.erb +31 -31
- data/templates/src/include/ast_nodes.h.erb +10 -9
- data/templates/src/include/ast_pretty_print.h.erb +2 -2
- data/templates/src/include/errors.h.erb +6 -6
- data/templates/src/parser_match_tags.c.erb +38 -0
- data/templates/src/visitor.c.erb +4 -4
- data/templates/template.rb +22 -3
- data/templates/wasm/error_helpers.cpp.erb +9 -9
- data/templates/wasm/error_helpers.h.erb +1 -1
- data/templates/wasm/nodes.cpp.erb +9 -9
- data/templates/wasm/nodes.h.erb +1 -1
- data/vendor/prism/Rakefile +4 -1
- data/vendor/prism/config.yml +2 -1
- data/vendor/prism/include/prism/ast.h +31 -1
- data/vendor/prism/include/prism/diagnostic.h +1 -0
- data/vendor/prism/include/prism/version.h +3 -3
- data/vendor/prism/src/diagnostic.c +3 -1
- data/vendor/prism/src/prism.c +130 -71
- data/vendor/prism/src/util/pm_string.c +6 -8
- data/vendor/prism/templates/include/prism/ast.h.erb +2 -0
- data/vendor/prism/templates/java/org/prism/Loader.java.erb +2 -2
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +2 -2
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +2 -2
- data/vendor/prism/templates/sig/prism.rbs.erb +4 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +1 -0
- metadata +34 -20
- data/lib/herb/libherb/array.rb +0 -51
- data/lib/herb/libherb/ast_node.rb +0 -50
- data/lib/herb/libherb/buffer.rb +0 -56
- data/lib/herb/libherb/extract_result.rb +0 -20
- data/lib/herb/libherb/lex_result.rb +0 -32
- data/lib/herb/libherb/libherb.rb +0 -52
- data/lib/herb/libherb/parse_result.rb +0 -20
- data/lib/herb/libherb/token.rb +0 -46
- data/lib/herb/libherb.rb +0 -35
- data/src/buffer.c +0 -241
- data/src/include/array.h +0 -33
- data/src/include/buffer.h +0 -39
- data/src/include/json.h +0 -28
- data/src/include/memory.h +0 -12
- data/src/json.c +0 -205
- data/src/memory.c +0 -53
data/src/analyze.c
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
#include "include/analyze.h"
|
|
2
2
|
#include "include/analyze_helpers.h"
|
|
3
3
|
#include "include/analyzed_ruby.h"
|
|
4
|
-
#include "include/
|
|
4
|
+
#include "include/ast_node.h"
|
|
5
5
|
#include "include/ast_nodes.h"
|
|
6
6
|
#include "include/errors.h"
|
|
7
7
|
#include "include/extract.h"
|
|
8
8
|
#include "include/location.h"
|
|
9
|
+
#include "include/parser.h"
|
|
9
10
|
#include "include/position.h"
|
|
10
11
|
#include "include/pretty_print.h"
|
|
11
12
|
#include "include/prism_helpers.h"
|
|
12
13
|
#include "include/token_struct.h"
|
|
13
14
|
#include "include/util.h"
|
|
15
|
+
#include "include/util/hb_array.h"
|
|
16
|
+
#include "include/util/hb_string.h"
|
|
14
17
|
#include "include/visitor.h"
|
|
15
18
|
|
|
16
19
|
#include <prism.h>
|
|
@@ -19,7 +22,7 @@
|
|
|
19
22
|
#include <stdlib.h>
|
|
20
23
|
#include <string.h>
|
|
21
24
|
|
|
22
|
-
static analyzed_ruby_T* herb_analyze_ruby(
|
|
25
|
+
static analyzed_ruby_T* herb_analyze_ruby(hb_string_T source) {
|
|
23
26
|
analyzed_ruby_T* analyzed = init_analyzed_ruby(source);
|
|
24
27
|
|
|
25
28
|
pm_visit_node(analyzed->root, search_if_nodes, analyzed);
|
|
@@ -52,9 +55,7 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) {
|
|
|
52
55
|
const char* opening = erb_content_node->tag_opening->value;
|
|
53
56
|
|
|
54
57
|
if (strcmp(opening, "<%%") != 0 && strcmp(opening, "<%%=") != 0 && strcmp(opening, "<%#") != 0) {
|
|
55
|
-
analyzed_ruby_T* analyzed = herb_analyze_ruby(erb_content_node->content->value);
|
|
56
|
-
|
|
57
|
-
if (false) { pretty_print_analyzed_ruby(analyzed, erb_content_node->content->value); }
|
|
58
|
+
analyzed_ruby_T* analyzed = herb_analyze_ruby(hb_string(erb_content_node->content->value));
|
|
58
59
|
|
|
59
60
|
erb_content_node->parsed = true;
|
|
60
61
|
erb_content_node->valid = analyzed->valid;
|
|
@@ -73,16 +74,16 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) {
|
|
|
73
74
|
|
|
74
75
|
static size_t process_block_children(
|
|
75
76
|
AST_NODE_T* node,
|
|
76
|
-
|
|
77
|
+
hb_array_T* array,
|
|
77
78
|
size_t index,
|
|
78
|
-
|
|
79
|
+
hb_array_T* children_array,
|
|
79
80
|
analyze_ruby_context_T* context,
|
|
80
81
|
control_type_t parent_type
|
|
81
82
|
);
|
|
82
83
|
|
|
83
84
|
static size_t process_subsequent_block(
|
|
84
85
|
AST_NODE_T* node,
|
|
85
|
-
|
|
86
|
+
hb_array_T* array,
|
|
86
87
|
size_t index,
|
|
87
88
|
AST_NODE_T** subsequent_out,
|
|
88
89
|
analyze_ruby_context_T* context,
|
|
@@ -149,19 +150,21 @@ static bool is_terminator_type(control_type_t parent_type, control_type_t child_
|
|
|
149
150
|
|
|
150
151
|
static AST_NODE_T* create_control_node(
|
|
151
152
|
AST_ERB_CONTENT_NODE_T* erb_node,
|
|
152
|
-
|
|
153
|
+
hb_array_T* children,
|
|
153
154
|
AST_NODE_T* subsequent,
|
|
154
155
|
AST_ERB_END_NODE_T* end_node,
|
|
155
156
|
control_type_t control_type
|
|
156
157
|
) {
|
|
157
|
-
|
|
158
|
+
hb_array_T* errors = erb_node->base.errors;
|
|
159
|
+
erb_node->base.errors = NULL;
|
|
160
|
+
|
|
158
161
|
position_T start_position = erb_node->tag_opening->location.start;
|
|
159
162
|
position_T end_position = erb_node->tag_closing->location.end;
|
|
160
163
|
|
|
161
164
|
if (end_node) {
|
|
162
165
|
end_position = end_node->base.location.end;
|
|
163
|
-
} else if (children &&
|
|
164
|
-
AST_NODE_T* last_child =
|
|
166
|
+
} else if (children && hb_array_size(children) > 0) {
|
|
167
|
+
AST_NODE_T* last_child = hb_array_get(children, hb_array_size(children) - 1);
|
|
165
168
|
end_position = last_child->location.end;
|
|
166
169
|
} else if (subsequent) {
|
|
167
170
|
end_position = subsequent->location.end;
|
|
@@ -173,7 +176,7 @@ static AST_NODE_T* create_control_node(
|
|
|
173
176
|
|
|
174
177
|
switch (control_type) {
|
|
175
178
|
case CONTROL_TYPE_IF:
|
|
176
|
-
case CONTROL_TYPE_ELSIF:
|
|
179
|
+
case CONTROL_TYPE_ELSIF: {
|
|
177
180
|
return (AST_NODE_T*) ast_erb_if_node_init(
|
|
178
181
|
tag_opening,
|
|
179
182
|
content,
|
|
@@ -185,32 +188,40 @@ static AST_NODE_T* create_control_node(
|
|
|
185
188
|
end_position,
|
|
186
189
|
errors
|
|
187
190
|
);
|
|
191
|
+
}
|
|
188
192
|
|
|
189
|
-
case CONTROL_TYPE_ELSE:
|
|
190
|
-
return (
|
|
191
|
-
|
|
193
|
+
case CONTROL_TYPE_ELSE: {
|
|
194
|
+
return (
|
|
195
|
+
AST_NODE_T*
|
|
196
|
+
) ast_erb_else_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
197
|
+
}
|
|
192
198
|
|
|
193
199
|
case CONTROL_TYPE_CASE:
|
|
194
200
|
case CONTROL_TYPE_CASE_MATCH: {
|
|
195
201
|
AST_ERB_ELSE_NODE_T* else_node = NULL;
|
|
196
202
|
if (subsequent && subsequent->type == AST_ERB_ELSE_NODE) { else_node = (AST_ERB_ELSE_NODE_T*) subsequent; }
|
|
197
203
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
hb_array_T* when_conditions = hb_array_init(8);
|
|
205
|
+
hb_array_T* in_conditions = hb_array_init(8);
|
|
206
|
+
hb_array_T* non_when_non_in_children = hb_array_init(8);
|
|
207
|
+
|
|
208
|
+
for (size_t i = 0; i < hb_array_size(children); i++) {
|
|
209
|
+
AST_NODE_T* child = hb_array_get(children, i);
|
|
201
210
|
|
|
202
|
-
for (size_t i = 0; i < array_size(children); i++) {
|
|
203
|
-
AST_NODE_T* child = array_get(children, i);
|
|
204
211
|
if (child && child->type == AST_ERB_WHEN_NODE) {
|
|
205
|
-
|
|
212
|
+
hb_array_append(when_conditions, child);
|
|
206
213
|
} else if (child && child->type == AST_ERB_IN_NODE) {
|
|
207
|
-
|
|
214
|
+
hb_array_append(in_conditions, child);
|
|
208
215
|
} else {
|
|
209
|
-
|
|
216
|
+
hb_array_append(non_when_non_in_children, child);
|
|
210
217
|
}
|
|
211
218
|
}
|
|
212
219
|
|
|
213
|
-
|
|
220
|
+
hb_array_free(&children);
|
|
221
|
+
|
|
222
|
+
if (hb_array_size(in_conditions) > 0) {
|
|
223
|
+
hb_array_free(&when_conditions);
|
|
224
|
+
|
|
214
225
|
return (AST_NODE_T*) ast_erb_case_match_node_init(
|
|
215
226
|
tag_opening,
|
|
216
227
|
content,
|
|
@@ -223,30 +234,34 @@ static AST_NODE_T* create_control_node(
|
|
|
223
234
|
end_position,
|
|
224
235
|
errors
|
|
225
236
|
);
|
|
226
|
-
}
|
|
237
|
+
} else {
|
|
238
|
+
hb_array_free(&in_conditions);
|
|
227
239
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
+
return (AST_NODE_T*) ast_erb_case_node_init(
|
|
241
|
+
tag_opening,
|
|
242
|
+
content,
|
|
243
|
+
tag_closing,
|
|
244
|
+
non_when_non_in_children,
|
|
245
|
+
when_conditions,
|
|
246
|
+
else_node,
|
|
247
|
+
end_node,
|
|
248
|
+
start_position,
|
|
249
|
+
end_position,
|
|
250
|
+
errors
|
|
251
|
+
);
|
|
252
|
+
}
|
|
240
253
|
}
|
|
241
254
|
|
|
242
255
|
case CONTROL_TYPE_WHEN: {
|
|
243
|
-
return (
|
|
244
|
-
|
|
256
|
+
return (
|
|
257
|
+
AST_NODE_T*
|
|
258
|
+
) ast_erb_when_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
245
259
|
}
|
|
246
260
|
|
|
247
261
|
case CONTROL_TYPE_IN: {
|
|
248
|
-
return (
|
|
249
|
-
|
|
262
|
+
return (
|
|
263
|
+
AST_NODE_T*
|
|
264
|
+
) ast_erb_in_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
250
265
|
}
|
|
251
266
|
|
|
252
267
|
case CONTROL_TYPE_BEGIN: {
|
|
@@ -297,8 +312,9 @@ static AST_NODE_T* create_control_node(
|
|
|
297
312
|
}
|
|
298
313
|
|
|
299
314
|
case CONTROL_TYPE_ENSURE: {
|
|
300
|
-
return (
|
|
301
|
-
|
|
315
|
+
return (
|
|
316
|
+
AST_NODE_T*
|
|
317
|
+
) ast_erb_ensure_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
302
318
|
}
|
|
303
319
|
|
|
304
320
|
case CONTROL_TYPE_UNLESS: {
|
|
@@ -372,34 +388,35 @@ static AST_NODE_T* create_control_node(
|
|
|
372
388
|
}
|
|
373
389
|
|
|
374
390
|
case CONTROL_TYPE_YIELD: {
|
|
375
|
-
return (
|
|
376
|
-
|
|
391
|
+
return (
|
|
392
|
+
AST_NODE_T*
|
|
393
|
+
) ast_erb_yield_node_init(tag_opening, content, tag_closing, start_position, end_position, errors);
|
|
377
394
|
}
|
|
378
395
|
|
|
379
|
-
default:
|
|
396
|
+
default: return NULL;
|
|
380
397
|
}
|
|
381
398
|
}
|
|
382
399
|
|
|
383
400
|
static size_t process_control_structure(
|
|
384
401
|
AST_NODE_T* node,
|
|
385
|
-
|
|
402
|
+
hb_array_T* array,
|
|
386
403
|
size_t index,
|
|
387
|
-
|
|
404
|
+
hb_array_T* output_array,
|
|
388
405
|
analyze_ruby_context_T* context,
|
|
389
406
|
control_type_t initial_type
|
|
390
407
|
) {
|
|
391
|
-
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*)
|
|
392
|
-
|
|
408
|
+
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*) hb_array_get(array, index);
|
|
409
|
+
hb_array_T* children = hb_array_init(8);
|
|
393
410
|
|
|
394
411
|
index++;
|
|
395
412
|
|
|
396
413
|
if (initial_type == CONTROL_TYPE_CASE || initial_type == CONTROL_TYPE_CASE_MATCH) {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
414
|
+
hb_array_T* when_conditions = hb_array_init(8);
|
|
415
|
+
hb_array_T* in_conditions = hb_array_init(8);
|
|
416
|
+
hb_array_T* non_when_non_in_children = hb_array_init(8);
|
|
400
417
|
|
|
401
|
-
while (index <
|
|
402
|
-
AST_NODE_T* next_node =
|
|
418
|
+
while (index < hb_array_size(array)) {
|
|
419
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
403
420
|
|
|
404
421
|
if (!next_node) { break; }
|
|
405
422
|
|
|
@@ -410,17 +427,17 @@ static size_t process_control_structure(
|
|
|
410
427
|
if (next_type == CONTROL_TYPE_WHEN || next_type == CONTROL_TYPE_IN) { break; }
|
|
411
428
|
}
|
|
412
429
|
|
|
413
|
-
|
|
430
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
414
431
|
index++;
|
|
415
432
|
}
|
|
416
433
|
|
|
417
|
-
while (index <
|
|
418
|
-
AST_NODE_T* next_node =
|
|
434
|
+
while (index < hb_array_size(array)) {
|
|
435
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
419
436
|
|
|
420
437
|
if (!next_node) { break; }
|
|
421
438
|
|
|
422
439
|
if (next_node->type != AST_ERB_CONTENT_NODE) {
|
|
423
|
-
|
|
440
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
424
441
|
index++;
|
|
425
442
|
continue;
|
|
426
443
|
}
|
|
@@ -429,11 +446,14 @@ static size_t process_control_structure(
|
|
|
429
446
|
control_type_t next_type = detect_control_type(erb_content);
|
|
430
447
|
|
|
431
448
|
if (next_type == CONTROL_TYPE_WHEN) {
|
|
432
|
-
|
|
449
|
+
hb_array_T* when_statements = hb_array_init(8);
|
|
433
450
|
index++;
|
|
434
451
|
|
|
435
452
|
index = process_block_children(node, array, index, when_statements, context, CONTROL_TYPE_WHEN);
|
|
436
453
|
|
|
454
|
+
hb_array_T* when_errors = erb_content->base.errors;
|
|
455
|
+
erb_content->base.errors = NULL;
|
|
456
|
+
|
|
437
457
|
AST_ERB_WHEN_NODE_T* when_node = ast_erb_when_node_init(
|
|
438
458
|
erb_content->tag_opening,
|
|
439
459
|
erb_content->content,
|
|
@@ -441,18 +461,23 @@ static size_t process_control_structure(
|
|
|
441
461
|
when_statements,
|
|
442
462
|
erb_content->tag_opening->location.start,
|
|
443
463
|
erb_content->tag_closing->location.end,
|
|
444
|
-
|
|
464
|
+
when_errors
|
|
445
465
|
);
|
|
446
466
|
|
|
447
|
-
|
|
467
|
+
ast_node_free((AST_NODE_T*) erb_content);
|
|
468
|
+
|
|
469
|
+
hb_array_append(when_conditions, (AST_NODE_T*) when_node);
|
|
448
470
|
|
|
449
471
|
continue;
|
|
450
472
|
} else if (next_type == CONTROL_TYPE_IN) {
|
|
451
|
-
|
|
473
|
+
hb_array_T* in_statements = hb_array_init(8);
|
|
452
474
|
index++;
|
|
453
475
|
|
|
454
476
|
index = process_block_children(node, array, index, in_statements, context, CONTROL_TYPE_IN);
|
|
455
477
|
|
|
478
|
+
hb_array_T* in_errors = erb_content->base.errors;
|
|
479
|
+
erb_content->base.errors = NULL;
|
|
480
|
+
|
|
456
481
|
AST_ERB_IN_NODE_T* in_node = ast_erb_in_node_init(
|
|
457
482
|
erb_content->tag_opening,
|
|
458
483
|
erb_content->content,
|
|
@@ -460,36 +485,38 @@ static size_t process_control_structure(
|
|
|
460
485
|
in_statements,
|
|
461
486
|
erb_content->tag_opening->location.start,
|
|
462
487
|
erb_content->tag_closing->location.end,
|
|
463
|
-
|
|
488
|
+
in_errors
|
|
464
489
|
);
|
|
465
490
|
|
|
466
|
-
|
|
491
|
+
ast_node_free((AST_NODE_T*) erb_content);
|
|
492
|
+
|
|
493
|
+
hb_array_append(in_conditions, (AST_NODE_T*) in_node);
|
|
467
494
|
|
|
468
495
|
continue;
|
|
469
496
|
} else if (next_type == CONTROL_TYPE_ELSE || next_type == CONTROL_TYPE_END) {
|
|
470
497
|
break;
|
|
471
498
|
} else {
|
|
472
|
-
|
|
499
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
473
500
|
index++;
|
|
474
501
|
}
|
|
475
502
|
}
|
|
476
503
|
|
|
477
504
|
AST_ERB_ELSE_NODE_T* else_clause = NULL;
|
|
478
505
|
|
|
479
|
-
if (index <
|
|
480
|
-
AST_NODE_T* next_node =
|
|
506
|
+
if (index < hb_array_size(array)) {
|
|
507
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
481
508
|
|
|
482
509
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
483
510
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
484
511
|
control_type_t next_type = detect_control_type(next_erb);
|
|
485
512
|
|
|
486
513
|
if (next_type == CONTROL_TYPE_ELSE) {
|
|
487
|
-
|
|
514
|
+
hb_array_T* else_children = hb_array_init(8);
|
|
488
515
|
|
|
489
516
|
index++;
|
|
490
517
|
|
|
491
|
-
while (index <
|
|
492
|
-
AST_NODE_T* child =
|
|
518
|
+
while (index < hb_array_size(array)) {
|
|
519
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
493
520
|
|
|
494
521
|
if (!child) { break; }
|
|
495
522
|
|
|
@@ -500,10 +527,13 @@ static size_t process_control_structure(
|
|
|
500
527
|
if (child_type == CONTROL_TYPE_END) { break; }
|
|
501
528
|
}
|
|
502
529
|
|
|
503
|
-
|
|
530
|
+
hb_array_append(else_children, child);
|
|
504
531
|
index++;
|
|
505
532
|
}
|
|
506
533
|
|
|
534
|
+
hb_array_T* else_errors = next_erb->base.errors;
|
|
535
|
+
next_erb->base.errors = NULL;
|
|
536
|
+
|
|
507
537
|
else_clause = ast_erb_else_node_init(
|
|
508
538
|
next_erb->tag_opening,
|
|
509
539
|
next_erb->content,
|
|
@@ -511,30 +541,37 @@ static size_t process_control_structure(
|
|
|
511
541
|
else_children,
|
|
512
542
|
next_erb->tag_opening->location.start,
|
|
513
543
|
next_erb->tag_closing->location.end,
|
|
514
|
-
|
|
544
|
+
else_errors
|
|
515
545
|
);
|
|
546
|
+
|
|
547
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
516
548
|
}
|
|
517
549
|
}
|
|
518
550
|
}
|
|
519
551
|
|
|
520
552
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
521
553
|
|
|
522
|
-
if (index <
|
|
523
|
-
AST_NODE_T* potential_end =
|
|
554
|
+
if (index < hb_array_size(array)) {
|
|
555
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
524
556
|
|
|
525
557
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
526
558
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
527
559
|
|
|
528
560
|
if (detect_control_type(end_erb) == CONTROL_TYPE_END) {
|
|
561
|
+
hb_array_T* end_errors = end_erb->base.errors;
|
|
562
|
+
end_erb->base.errors = NULL;
|
|
563
|
+
|
|
529
564
|
end_node = ast_erb_end_node_init(
|
|
530
565
|
end_erb->tag_opening,
|
|
531
566
|
end_erb->content,
|
|
532
567
|
end_erb->tag_closing,
|
|
533
568
|
end_erb->tag_opening->location.start,
|
|
534
569
|
end_erb->tag_closing->location.end,
|
|
535
|
-
|
|
570
|
+
end_errors
|
|
536
571
|
);
|
|
537
572
|
|
|
573
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
574
|
+
|
|
538
575
|
index++;
|
|
539
576
|
}
|
|
540
577
|
}
|
|
@@ -547,15 +584,18 @@ static size_t process_control_structure(
|
|
|
547
584
|
end_position = end_node->base.location.end;
|
|
548
585
|
} else if (else_clause) {
|
|
549
586
|
end_position = else_clause->base.location.end;
|
|
550
|
-
} else if (
|
|
551
|
-
AST_NODE_T* last_when =
|
|
587
|
+
} else if (hb_array_size(when_conditions) > 0) {
|
|
588
|
+
AST_NODE_T* last_when = hb_array_get(when_conditions, hb_array_size(when_conditions) - 1);
|
|
552
589
|
end_position = last_when->location.end;
|
|
553
|
-
} else if (
|
|
554
|
-
AST_NODE_T* last_in =
|
|
590
|
+
} else if (hb_array_size(in_conditions) > 0) {
|
|
591
|
+
AST_NODE_T* last_in = hb_array_get(in_conditions, hb_array_size(in_conditions) - 1);
|
|
555
592
|
end_position = last_in->location.end;
|
|
556
593
|
}
|
|
557
594
|
|
|
558
|
-
if (
|
|
595
|
+
if (hb_array_size(in_conditions) > 0) {
|
|
596
|
+
hb_array_T* case_match_errors = erb_node->base.errors;
|
|
597
|
+
erb_node->base.errors = NULL;
|
|
598
|
+
|
|
559
599
|
AST_ERB_CASE_MATCH_NODE_T* case_match_node = ast_erb_case_match_node_init(
|
|
560
600
|
erb_node->tag_opening,
|
|
561
601
|
erb_node->content,
|
|
@@ -566,13 +606,21 @@ static size_t process_control_structure(
|
|
|
566
606
|
end_node,
|
|
567
607
|
start_position,
|
|
568
608
|
end_position,
|
|
569
|
-
|
|
609
|
+
case_match_errors
|
|
570
610
|
);
|
|
571
611
|
|
|
572
|
-
|
|
612
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
613
|
+
|
|
614
|
+
hb_array_append(output_array, (AST_NODE_T*) case_match_node);
|
|
615
|
+
hb_array_free(&when_conditions);
|
|
616
|
+
hb_array_free(&children);
|
|
617
|
+
|
|
573
618
|
return index;
|
|
574
619
|
}
|
|
575
620
|
|
|
621
|
+
hb_array_T* case_errors = erb_node->base.errors;
|
|
622
|
+
erb_node->base.errors = NULL;
|
|
623
|
+
|
|
576
624
|
AST_ERB_CASE_NODE_T* case_node = ast_erb_case_node_init(
|
|
577
625
|
erb_node->tag_opening,
|
|
578
626
|
erb_node->content,
|
|
@@ -583,10 +631,15 @@ static size_t process_control_structure(
|
|
|
583
631
|
end_node,
|
|
584
632
|
start_position,
|
|
585
633
|
end_position,
|
|
586
|
-
|
|
634
|
+
case_errors
|
|
587
635
|
);
|
|
588
636
|
|
|
589
|
-
|
|
637
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
638
|
+
|
|
639
|
+
hb_array_append(output_array, (AST_NODE_T*) case_node);
|
|
640
|
+
hb_array_free(&in_conditions);
|
|
641
|
+
hb_array_free(&children);
|
|
642
|
+
|
|
590
643
|
return index;
|
|
591
644
|
}
|
|
592
645
|
|
|
@@ -597,8 +650,8 @@ static size_t process_control_structure(
|
|
|
597
650
|
AST_ERB_ELSE_NODE_T* else_clause = NULL;
|
|
598
651
|
AST_ERB_ENSURE_NODE_T* ensure_clause = NULL;
|
|
599
652
|
|
|
600
|
-
if (index <
|
|
601
|
-
AST_NODE_T* next_node =
|
|
653
|
+
if (index < hb_array_size(array)) {
|
|
654
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
602
655
|
|
|
603
656
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
604
657
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -612,20 +665,20 @@ static size_t process_control_structure(
|
|
|
612
665
|
}
|
|
613
666
|
}
|
|
614
667
|
|
|
615
|
-
if (index <
|
|
616
|
-
AST_NODE_T* next_node =
|
|
668
|
+
if (index < hb_array_size(array)) {
|
|
669
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
617
670
|
|
|
618
671
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
619
672
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
620
673
|
control_type_t next_type = detect_control_type(next_erb);
|
|
621
674
|
|
|
622
675
|
if (next_type == CONTROL_TYPE_ELSE) {
|
|
623
|
-
|
|
676
|
+
hb_array_T* else_children = hb_array_init(8);
|
|
624
677
|
|
|
625
678
|
index++;
|
|
626
679
|
|
|
627
|
-
while (index <
|
|
628
|
-
AST_NODE_T* child =
|
|
680
|
+
while (index < hb_array_size(array)) {
|
|
681
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
629
682
|
|
|
630
683
|
if (!child) { break; }
|
|
631
684
|
|
|
@@ -636,10 +689,13 @@ static size_t process_control_structure(
|
|
|
636
689
|
if (child_type == CONTROL_TYPE_ENSURE || child_type == CONTROL_TYPE_END) { break; }
|
|
637
690
|
}
|
|
638
691
|
|
|
639
|
-
|
|
692
|
+
hb_array_append(else_children, child);
|
|
640
693
|
index++;
|
|
641
694
|
}
|
|
642
695
|
|
|
696
|
+
hb_array_T* else_errors = next_erb->base.errors;
|
|
697
|
+
next_erb->base.errors = NULL;
|
|
698
|
+
|
|
643
699
|
else_clause = ast_erb_else_node_init(
|
|
644
700
|
next_erb->tag_opening,
|
|
645
701
|
next_erb->content,
|
|
@@ -647,26 +703,28 @@ static size_t process_control_structure(
|
|
|
647
703
|
else_children,
|
|
648
704
|
next_erb->tag_opening->location.start,
|
|
649
705
|
next_erb->tag_closing->location.end,
|
|
650
|
-
|
|
706
|
+
else_errors
|
|
651
707
|
);
|
|
708
|
+
|
|
709
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
652
710
|
}
|
|
653
711
|
}
|
|
654
712
|
}
|
|
655
713
|
|
|
656
|
-
if (index <
|
|
657
|
-
AST_NODE_T* next_node =
|
|
714
|
+
if (index < hb_array_size(array)) {
|
|
715
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
658
716
|
|
|
659
717
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
660
718
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
661
719
|
control_type_t next_type = detect_control_type(next_erb);
|
|
662
720
|
|
|
663
721
|
if (next_type == CONTROL_TYPE_ENSURE) {
|
|
664
|
-
|
|
722
|
+
hb_array_T* ensure_children = hb_array_init(8);
|
|
665
723
|
|
|
666
724
|
index++;
|
|
667
725
|
|
|
668
|
-
while (index <
|
|
669
|
-
AST_NODE_T* child =
|
|
726
|
+
while (index < hb_array_size(array)) {
|
|
727
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
670
728
|
|
|
671
729
|
if (!child) { break; }
|
|
672
730
|
|
|
@@ -677,10 +735,13 @@ static size_t process_control_structure(
|
|
|
677
735
|
if (child_type == CONTROL_TYPE_END) { break; }
|
|
678
736
|
}
|
|
679
737
|
|
|
680
|
-
|
|
738
|
+
hb_array_append(ensure_children, child);
|
|
681
739
|
index++;
|
|
682
740
|
}
|
|
683
741
|
|
|
742
|
+
hb_array_T* ensure_errors = next_erb->base.errors;
|
|
743
|
+
next_erb->base.errors = NULL;
|
|
744
|
+
|
|
684
745
|
ensure_clause = ast_erb_ensure_node_init(
|
|
685
746
|
next_erb->tag_opening,
|
|
686
747
|
next_erb->content,
|
|
@@ -688,30 +749,37 @@ static size_t process_control_structure(
|
|
|
688
749
|
ensure_children,
|
|
689
750
|
next_erb->tag_opening->location.start,
|
|
690
751
|
next_erb->tag_closing->location.end,
|
|
691
|
-
|
|
752
|
+
ensure_errors
|
|
692
753
|
);
|
|
754
|
+
|
|
755
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
693
756
|
}
|
|
694
757
|
}
|
|
695
758
|
}
|
|
696
759
|
|
|
697
760
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
698
761
|
|
|
699
|
-
if (index <
|
|
700
|
-
AST_NODE_T* potential_end =
|
|
762
|
+
if (index < hb_array_size(array)) {
|
|
763
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
701
764
|
|
|
702
765
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
703
766
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
704
767
|
|
|
705
768
|
if (detect_control_type(end_erb) == CONTROL_TYPE_END) {
|
|
769
|
+
hb_array_T* end_errors = end_erb->base.errors;
|
|
770
|
+
end_erb->base.errors = NULL;
|
|
771
|
+
|
|
706
772
|
end_node = ast_erb_end_node_init(
|
|
707
773
|
end_erb->tag_opening,
|
|
708
774
|
end_erb->content,
|
|
709
775
|
end_erb->tag_closing,
|
|
710
776
|
end_erb->tag_opening->location.start,
|
|
711
777
|
end_erb->tag_closing->location.end,
|
|
712
|
-
|
|
778
|
+
end_errors
|
|
713
779
|
);
|
|
714
780
|
|
|
781
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
782
|
+
|
|
715
783
|
index++;
|
|
716
784
|
}
|
|
717
785
|
}
|
|
@@ -730,6 +798,9 @@ static size_t process_control_structure(
|
|
|
730
798
|
end_position = rescue_clause->base.location.end;
|
|
731
799
|
}
|
|
732
800
|
|
|
801
|
+
hb_array_T* begin_errors = erb_node->base.errors;
|
|
802
|
+
erb_node->base.errors = NULL;
|
|
803
|
+
|
|
733
804
|
AST_ERB_BEGIN_NODE_T* begin_node = ast_erb_begin_node_init(
|
|
734
805
|
erb_node->tag_opening,
|
|
735
806
|
erb_node->content,
|
|
@@ -741,10 +812,12 @@ static size_t process_control_structure(
|
|
|
741
812
|
end_node,
|
|
742
813
|
start_position,
|
|
743
814
|
end_position,
|
|
744
|
-
|
|
815
|
+
begin_errors
|
|
745
816
|
);
|
|
746
817
|
|
|
747
|
-
|
|
818
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
819
|
+
|
|
820
|
+
hb_array_append(output_array, (AST_NODE_T*) begin_node);
|
|
748
821
|
return index;
|
|
749
822
|
}
|
|
750
823
|
|
|
@@ -753,23 +826,28 @@ static size_t process_control_structure(
|
|
|
753
826
|
|
|
754
827
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
755
828
|
|
|
756
|
-
if (index <
|
|
757
|
-
AST_NODE_T* potential_close =
|
|
829
|
+
if (index < hb_array_size(array)) {
|
|
830
|
+
AST_NODE_T* potential_close = hb_array_get(array, index);
|
|
758
831
|
|
|
759
832
|
if (potential_close && potential_close->type == AST_ERB_CONTENT_NODE) {
|
|
760
833
|
AST_ERB_CONTENT_NODE_T* close_erb = (AST_ERB_CONTENT_NODE_T*) potential_close;
|
|
761
834
|
control_type_t close_type = detect_control_type(close_erb);
|
|
762
835
|
|
|
763
836
|
if (close_type == CONTROL_TYPE_BLOCK_CLOSE || close_type == CONTROL_TYPE_END) {
|
|
837
|
+
hb_array_T* end_errors = close_erb->base.errors;
|
|
838
|
+
close_erb->base.errors = NULL;
|
|
839
|
+
|
|
764
840
|
end_node = ast_erb_end_node_init(
|
|
765
841
|
close_erb->tag_opening,
|
|
766
842
|
close_erb->content,
|
|
767
843
|
close_erb->tag_closing,
|
|
768
844
|
close_erb->tag_opening->location.start,
|
|
769
845
|
close_erb->tag_closing->location.end,
|
|
770
|
-
|
|
846
|
+
end_errors
|
|
771
847
|
);
|
|
772
848
|
|
|
849
|
+
ast_node_free((AST_NODE_T*) close_erb);
|
|
850
|
+
|
|
773
851
|
index++;
|
|
774
852
|
}
|
|
775
853
|
}
|
|
@@ -780,11 +858,14 @@ static size_t process_control_structure(
|
|
|
780
858
|
|
|
781
859
|
if (end_node) {
|
|
782
860
|
end_position = end_node->base.location.end;
|
|
783
|
-
} else if (children &&
|
|
784
|
-
AST_NODE_T* last_child =
|
|
861
|
+
} else if (children && hb_array_size(children) > 0) {
|
|
862
|
+
AST_NODE_T* last_child = hb_array_get(children, hb_array_size(children) - 1);
|
|
785
863
|
end_position = last_child->location.end;
|
|
786
864
|
}
|
|
787
865
|
|
|
866
|
+
hb_array_T* block_errors = erb_node->base.errors;
|
|
867
|
+
erb_node->base.errors = NULL;
|
|
868
|
+
|
|
788
869
|
AST_ERB_BLOCK_NODE_T* block_node = ast_erb_block_node_init(
|
|
789
870
|
erb_node->tag_opening,
|
|
790
871
|
erb_node->content,
|
|
@@ -793,10 +874,12 @@ static size_t process_control_structure(
|
|
|
793
874
|
end_node,
|
|
794
875
|
start_position,
|
|
795
876
|
end_position,
|
|
796
|
-
|
|
877
|
+
block_errors
|
|
797
878
|
);
|
|
798
879
|
|
|
799
|
-
|
|
880
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
881
|
+
|
|
882
|
+
hb_array_append(output_array, (AST_NODE_T*) block_node);
|
|
800
883
|
return index;
|
|
801
884
|
}
|
|
802
885
|
|
|
@@ -805,8 +888,8 @@ static size_t process_control_structure(
|
|
|
805
888
|
AST_NODE_T* subsequent = NULL;
|
|
806
889
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
807
890
|
|
|
808
|
-
if (index <
|
|
809
|
-
AST_NODE_T* next_node =
|
|
891
|
+
if (index < hb_array_size(array)) {
|
|
892
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
810
893
|
|
|
811
894
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
812
895
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -818,22 +901,27 @@ static size_t process_control_structure(
|
|
|
818
901
|
}
|
|
819
902
|
}
|
|
820
903
|
|
|
821
|
-
if (index <
|
|
822
|
-
AST_NODE_T* potential_end =
|
|
904
|
+
if (index < hb_array_size(array)) {
|
|
905
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
823
906
|
|
|
824
907
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
825
908
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
826
909
|
|
|
827
910
|
if (detect_control_type(end_erb) == CONTROL_TYPE_END) {
|
|
911
|
+
hb_array_T* end_errors = end_erb->base.errors;
|
|
912
|
+
end_erb->base.errors = NULL;
|
|
913
|
+
|
|
828
914
|
end_node = ast_erb_end_node_init(
|
|
829
915
|
end_erb->tag_opening,
|
|
830
916
|
end_erb->content,
|
|
831
917
|
end_erb->tag_closing,
|
|
832
918
|
end_erb->tag_opening->location.start,
|
|
833
919
|
end_erb->tag_closing->location.end,
|
|
834
|
-
|
|
920
|
+
end_errors
|
|
835
921
|
);
|
|
836
922
|
|
|
923
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
924
|
+
|
|
837
925
|
index++;
|
|
838
926
|
}
|
|
839
927
|
}
|
|
@@ -841,22 +929,27 @@ static size_t process_control_structure(
|
|
|
841
929
|
|
|
842
930
|
AST_NODE_T* control_node = create_control_node(erb_node, children, subsequent, end_node, initial_type);
|
|
843
931
|
|
|
844
|
-
if (control_node) {
|
|
932
|
+
if (control_node) {
|
|
933
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
934
|
+
hb_array_append(output_array, control_node);
|
|
935
|
+
} else {
|
|
936
|
+
hb_array_free(&children);
|
|
937
|
+
}
|
|
845
938
|
|
|
846
939
|
return index;
|
|
847
940
|
}
|
|
848
941
|
|
|
849
942
|
static size_t process_subsequent_block(
|
|
850
943
|
AST_NODE_T* node,
|
|
851
|
-
|
|
944
|
+
hb_array_T* array,
|
|
852
945
|
size_t index,
|
|
853
946
|
AST_NODE_T** subsequent_out,
|
|
854
947
|
analyze_ruby_context_T* context,
|
|
855
948
|
control_type_t parent_type
|
|
856
949
|
) {
|
|
857
|
-
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*)
|
|
950
|
+
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*) hb_array_get(array, index);
|
|
858
951
|
control_type_t type = detect_control_type(erb_node);
|
|
859
|
-
|
|
952
|
+
hb_array_T* children = hb_array_init(8);
|
|
860
953
|
|
|
861
954
|
index++;
|
|
862
955
|
|
|
@@ -864,8 +957,14 @@ static size_t process_subsequent_block(
|
|
|
864
957
|
|
|
865
958
|
AST_NODE_T* subsequent_node = create_control_node(erb_node, children, NULL, NULL, type);
|
|
866
959
|
|
|
867
|
-
if (
|
|
868
|
-
AST_NODE_T*
|
|
960
|
+
if (subsequent_node) {
|
|
961
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
962
|
+
} else {
|
|
963
|
+
hb_array_free(&children);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
if (index < hb_array_size(array)) {
|
|
967
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
869
968
|
|
|
870
969
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
871
970
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -916,19 +1015,19 @@ static size_t process_subsequent_block(
|
|
|
916
1015
|
|
|
917
1016
|
static size_t process_block_children(
|
|
918
1017
|
AST_NODE_T* node,
|
|
919
|
-
|
|
1018
|
+
hb_array_T* array,
|
|
920
1019
|
size_t index,
|
|
921
|
-
|
|
1020
|
+
hb_array_T* children_array,
|
|
922
1021
|
analyze_ruby_context_T* context,
|
|
923
1022
|
control_type_t parent_type
|
|
924
1023
|
) {
|
|
925
|
-
while (index <
|
|
926
|
-
AST_NODE_T* child =
|
|
1024
|
+
while (index < hb_array_size(array)) {
|
|
1025
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
927
1026
|
|
|
928
1027
|
if (!child) { break; }
|
|
929
1028
|
|
|
930
1029
|
if (child->type != AST_ERB_CONTENT_NODE) {
|
|
931
|
-
|
|
1030
|
+
hb_array_append(children_array, child);
|
|
932
1031
|
index++;
|
|
933
1032
|
continue;
|
|
934
1033
|
}
|
|
@@ -941,35 +1040,35 @@ static size_t process_block_children(
|
|
|
941
1040
|
if (child_type == CONTROL_TYPE_IF || child_type == CONTROL_TYPE_CASE || child_type == CONTROL_TYPE_CASE_MATCH
|
|
942
1041
|
|| child_type == CONTROL_TYPE_BEGIN || child_type == CONTROL_TYPE_UNLESS || child_type == CONTROL_TYPE_WHILE
|
|
943
1042
|
|| child_type == CONTROL_TYPE_UNTIL || child_type == CONTROL_TYPE_FOR || child_type == CONTROL_TYPE_BLOCK) {
|
|
944
|
-
|
|
1043
|
+
hb_array_T* temp_array = hb_array_init(1);
|
|
945
1044
|
size_t new_index = process_control_structure(node, array, index, temp_array, context, child_type);
|
|
946
1045
|
|
|
947
|
-
if (
|
|
1046
|
+
if (hb_array_size(temp_array) > 0) { hb_array_append(children_array, hb_array_get(temp_array, 0)); }
|
|
948
1047
|
|
|
949
|
-
|
|
1048
|
+
hb_array_free(&temp_array);
|
|
950
1049
|
|
|
951
1050
|
index = new_index;
|
|
952
1051
|
continue;
|
|
953
1052
|
}
|
|
954
1053
|
|
|
955
|
-
|
|
1054
|
+
hb_array_append(children_array, child);
|
|
956
1055
|
index++;
|
|
957
1056
|
}
|
|
958
1057
|
|
|
959
1058
|
return index;
|
|
960
1059
|
}
|
|
961
1060
|
|
|
962
|
-
|
|
963
|
-
|
|
1061
|
+
hb_array_T* rewrite_node_array(AST_NODE_T* node, hb_array_T* array, analyze_ruby_context_T* context) {
|
|
1062
|
+
hb_array_T* new_array = hb_array_init(hb_array_size(array));
|
|
964
1063
|
size_t index = 0;
|
|
965
1064
|
|
|
966
|
-
while (index <
|
|
967
|
-
AST_NODE_T* item =
|
|
1065
|
+
while (index < hb_array_size(array)) {
|
|
1066
|
+
AST_NODE_T* item = hb_array_get(array, index);
|
|
968
1067
|
|
|
969
1068
|
if (!item) { break; }
|
|
970
1069
|
|
|
971
1070
|
if (item->type != AST_ERB_CONTENT_NODE) {
|
|
972
|
-
|
|
1071
|
+
hb_array_append(new_array, item);
|
|
973
1072
|
index++;
|
|
974
1073
|
continue;
|
|
975
1074
|
}
|
|
@@ -991,12 +1090,13 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
991
1090
|
continue;
|
|
992
1091
|
|
|
993
1092
|
case CONTROL_TYPE_YIELD: {
|
|
994
|
-
AST_NODE_T* yield_node = create_control_node(erb_node,
|
|
1093
|
+
AST_NODE_T* yield_node = create_control_node(erb_node, NULL, NULL, NULL, type);
|
|
995
1094
|
|
|
996
1095
|
if (yield_node) {
|
|
997
|
-
|
|
1096
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
1097
|
+
hb_array_append(new_array, yield_node);
|
|
998
1098
|
} else {
|
|
999
|
-
|
|
1099
|
+
hb_array_append(new_array, item);
|
|
1000
1100
|
}
|
|
1001
1101
|
|
|
1002
1102
|
index++;
|
|
@@ -1004,7 +1104,7 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
1004
1104
|
}
|
|
1005
1105
|
|
|
1006
1106
|
default:
|
|
1007
|
-
|
|
1107
|
+
hb_array_append(new_array, item);
|
|
1008
1108
|
index++;
|
|
1009
1109
|
break;
|
|
1010
1110
|
}
|
|
@@ -1013,41 +1113,178 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
1013
1113
|
return new_array;
|
|
1014
1114
|
}
|
|
1015
1115
|
|
|
1016
|
-
static bool
|
|
1017
|
-
|
|
1018
|
-
|
|
1116
|
+
static bool detect_invalid_erb_structures(const AST_NODE_T* node, void* data) {
|
|
1117
|
+
invalid_erb_context_T* context = (invalid_erb_context_T*) data;
|
|
1118
|
+
|
|
1119
|
+
if (node->type == AST_HTML_ATTRIBUTE_NAME_NODE) { return false; }
|
|
1120
|
+
|
|
1121
|
+
bool is_loop_node =
|
|
1122
|
+
(node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE || node->type == AST_ERB_FOR_NODE
|
|
1123
|
+
|| node->type == AST_ERB_BLOCK_NODE);
|
|
1124
|
+
|
|
1125
|
+
bool is_begin_node = (node->type == AST_ERB_BEGIN_NODE);
|
|
1126
|
+
|
|
1127
|
+
if (is_loop_node) { context->loop_depth++; }
|
|
1128
|
+
|
|
1129
|
+
if (is_begin_node) { context->rescue_depth++; }
|
|
1019
1130
|
|
|
1020
|
-
if (node->type ==
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1131
|
+
if (node->type == AST_ERB_CONTENT_NODE) {
|
|
1132
|
+
const AST_ERB_CONTENT_NODE_T* content_node = (const AST_ERB_CONTENT_NODE_T*) node;
|
|
1133
|
+
|
|
1134
|
+
if (content_node->parsed && !content_node->valid && content_node->analyzed_ruby != NULL) {
|
|
1135
|
+
analyzed_ruby_T* analyzed = content_node->analyzed_ruby;
|
|
1136
|
+
|
|
1137
|
+
// =begin
|
|
1138
|
+
if (has_error_message(analyzed, "embedded document meets end of file")) {
|
|
1139
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1140
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1141
|
+
|
|
1142
|
+
return true;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// =end
|
|
1146
|
+
if (has_error_message(analyzed, "unexpected '=', ignoring it")
|
|
1147
|
+
&& has_error_message(analyzed, "unexpected 'end', ignoring it")) {
|
|
1148
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1149
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1150
|
+
|
|
1151
|
+
return true;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
const char* keyword = NULL;
|
|
1155
|
+
|
|
1156
|
+
if (context->loop_depth == 0) {
|
|
1157
|
+
if (has_error_message(analyzed, "Invalid break")) {
|
|
1158
|
+
keyword = "`<% break %>`";
|
|
1159
|
+
} else if (has_error_message(analyzed, "Invalid next")) {
|
|
1160
|
+
keyword = "`<% next %>`";
|
|
1161
|
+
} else if (has_error_message(analyzed, "Invalid redo")) {
|
|
1162
|
+
keyword = "`<% redo %>`";
|
|
1163
|
+
}
|
|
1164
|
+
} else {
|
|
1165
|
+
if (has_error_message(analyzed, "Invalid redo") || has_error_message(analyzed, "Invalid break")
|
|
1166
|
+
|| has_error_message(analyzed, "Invalid next")) {
|
|
1167
|
+
|
|
1168
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1169
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1170
|
+
|
|
1171
|
+
return true;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
if (context->rescue_depth == 0) {
|
|
1176
|
+
if (has_error_message(analyzed, "Invalid retry without rescue")) { keyword = "`<% retry %>`"; }
|
|
1177
|
+
} else {
|
|
1178
|
+
if (has_error_message(analyzed, "Invalid retry without rescue")) {
|
|
1179
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1180
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1181
|
+
|
|
1182
|
+
return true;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
if (keyword == NULL) { keyword = erb_keyword_from_analyzed_ruby(analyzed); }
|
|
1187
|
+
|
|
1188
|
+
if (keyword != NULL && !token_value_empty(content_node->tag_closing)) {
|
|
1189
|
+
append_erb_control_flow_scope_error(keyword, node->location.start, node->location.end, node->errors);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1025
1192
|
}
|
|
1026
1193
|
|
|
1027
|
-
if (node->type ==
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1194
|
+
if (node->type == AST_ERB_IF_NODE) {
|
|
1195
|
+
const AST_ERB_IF_NODE_T* if_node = (const AST_ERB_IF_NODE_T*) node;
|
|
1196
|
+
|
|
1197
|
+
if (if_node->end_node == NULL) { check_erb_node_for_missing_end(node); }
|
|
1198
|
+
|
|
1199
|
+
if (if_node->statements != NULL) {
|
|
1200
|
+
for (size_t i = 0; i < hb_array_size(if_node->statements); i++) {
|
|
1201
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(if_node->statements, i);
|
|
1202
|
+
|
|
1203
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
AST_NODE_T* subsequent = if_node->subsequent;
|
|
1208
|
+
|
|
1209
|
+
while (subsequent != NULL) {
|
|
1210
|
+
if (subsequent->type == AST_ERB_CONTENT_NODE) {
|
|
1211
|
+
const AST_ERB_CONTENT_NODE_T* content_node = (const AST_ERB_CONTENT_NODE_T*) subsequent;
|
|
1212
|
+
|
|
1213
|
+
if (content_node->parsed && !content_node->valid && content_node->analyzed_ruby != NULL) {
|
|
1214
|
+
analyzed_ruby_T* analyzed = content_node->analyzed_ruby;
|
|
1215
|
+
const char* keyword = erb_keyword_from_analyzed_ruby(analyzed);
|
|
1216
|
+
|
|
1217
|
+
if (!token_value_empty(content_node->tag_closing)) {
|
|
1218
|
+
append_erb_control_flow_scope_error(
|
|
1219
|
+
keyword,
|
|
1220
|
+
subsequent->location.start,
|
|
1221
|
+
subsequent->location.end,
|
|
1222
|
+
subsequent->errors
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
if (subsequent->type == AST_ERB_IF_NODE) {
|
|
1229
|
+
const AST_ERB_IF_NODE_T* elsif_node = (const AST_ERB_IF_NODE_T*) subsequent;
|
|
1230
|
+
|
|
1231
|
+
if (elsif_node->statements != NULL) {
|
|
1232
|
+
for (size_t i = 0; i < hb_array_size(elsif_node->statements); i++) {
|
|
1233
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(elsif_node->statements, i);
|
|
1234
|
+
|
|
1235
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
subsequent = elsif_node->subsequent;
|
|
1240
|
+
} else if (subsequent->type == AST_ERB_ELSE_NODE) {
|
|
1241
|
+
const AST_ERB_ELSE_NODE_T* else_node = (const AST_ERB_ELSE_NODE_T*) subsequent;
|
|
1242
|
+
|
|
1243
|
+
if (else_node->statements != NULL) {
|
|
1244
|
+
for (size_t i = 0; i < hb_array_size(else_node->statements); i++) {
|
|
1245
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(else_node->statements, i);
|
|
1246
|
+
|
|
1247
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
break;
|
|
1252
|
+
} else {
|
|
1253
|
+
break;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1032
1256
|
}
|
|
1033
1257
|
|
|
1034
|
-
if (node->type ==
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
array_free(&old_array);
|
|
1258
|
+
if (node->type == AST_ERB_UNLESS_NODE || node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE
|
|
1259
|
+
|| node->type == AST_ERB_FOR_NODE || node->type == AST_ERB_CASE_NODE || node->type == AST_ERB_CASE_MATCH_NODE
|
|
1260
|
+
|| node->type == AST_ERB_BEGIN_NODE || node->type == AST_ERB_BLOCK_NODE || node->type == AST_ERB_ELSE_NODE) {
|
|
1261
|
+
herb_visit_child_nodes(node, detect_invalid_erb_structures, context);
|
|
1039
1262
|
}
|
|
1040
1263
|
|
|
1041
|
-
if (node->type ==
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1264
|
+
if (node->type == AST_ERB_UNLESS_NODE || node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE
|
|
1265
|
+
|| node->type == AST_ERB_FOR_NODE || node->type == AST_ERB_CASE_NODE || node->type == AST_ERB_CASE_MATCH_NODE
|
|
1266
|
+
|| node->type == AST_ERB_BEGIN_NODE || node->type == AST_ERB_BLOCK_NODE || node->type == AST_ERB_ELSE_NODE) {
|
|
1267
|
+
check_erb_node_for_missing_end(node);
|
|
1268
|
+
|
|
1269
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1270
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1271
|
+
|
|
1272
|
+
return false;
|
|
1046
1273
|
}
|
|
1047
1274
|
|
|
1048
|
-
|
|
1275
|
+
if (node->type == AST_ERB_IF_NODE) {
|
|
1276
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1277
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1049
1278
|
|
|
1050
|
-
|
|
1279
|
+
return false;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
bool result = true;
|
|
1283
|
+
|
|
1284
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1285
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1286
|
+
|
|
1287
|
+
return result;
|
|
1051
1288
|
}
|
|
1052
1289
|
|
|
1053
1290
|
void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source) {
|
|
@@ -1056,19 +1293,31 @@ void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source)
|
|
|
1056
1293
|
analyze_ruby_context_T* context = malloc(sizeof(analyze_ruby_context_T));
|
|
1057
1294
|
context->document = document;
|
|
1058
1295
|
context->parent = NULL;
|
|
1059
|
-
context->ruby_context_stack =
|
|
1296
|
+
context->ruby_context_stack = hb_array_init(8);
|
|
1060
1297
|
|
|
1061
1298
|
herb_visit_node((AST_NODE_T*) document, transform_erb_nodes, context);
|
|
1062
1299
|
|
|
1300
|
+
invalid_erb_context_T* invalid_context = malloc(sizeof(invalid_erb_context_T));
|
|
1301
|
+
invalid_context->loop_depth = 0;
|
|
1302
|
+
invalid_context->rescue_depth = 0;
|
|
1303
|
+
|
|
1304
|
+
herb_visit_node((AST_NODE_T*) document, detect_invalid_erb_structures, invalid_context);
|
|
1305
|
+
|
|
1063
1306
|
herb_analyze_parse_errors(document, source);
|
|
1064
1307
|
|
|
1065
|
-
|
|
1308
|
+
herb_parser_match_html_tags_post_analyze(document);
|
|
1309
|
+
|
|
1310
|
+
hb_array_free(&context->ruby_context_stack);
|
|
1311
|
+
|
|
1066
1312
|
free(context);
|
|
1313
|
+
free(invalid_context);
|
|
1067
1314
|
}
|
|
1068
1315
|
|
|
1069
1316
|
void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source) {
|
|
1070
1317
|
char* extracted_ruby = herb_extract_ruby_with_semicolons(source);
|
|
1071
1318
|
|
|
1319
|
+
if (!extracted_ruby) { return; }
|
|
1320
|
+
|
|
1072
1321
|
pm_parser_t parser;
|
|
1073
1322
|
pm_options_t options = { 0, .partial_script = true };
|
|
1074
1323
|
pm_parser_init(&parser, (const uint8_t*) extracted_ruby, strlen(extracted_ruby), &options);
|
|
@@ -1079,7 +1328,7 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source
|
|
|
1079
1328
|
error = (const pm_diagnostic_t*) error->node.next) {
|
|
1080
1329
|
|
|
1081
1330
|
RUBY_PARSE_ERROR_T* parse_error = ruby_parse_error_from_prism_error(error, (AST_NODE_T*) document, source, &parser);
|
|
1082
|
-
|
|
1331
|
+
hb_array_append(document->base.errors, parse_error);
|
|
1083
1332
|
}
|
|
1084
1333
|
|
|
1085
1334
|
pm_node_destroy(&parser, root);
|