herb 0.7.5-x86_64-darwin → 0.8.1-x86_64-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/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/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 +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 +549 -204
- data/src/analyze_helpers.c +17 -4
- 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 +33 -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 +280 -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 +194 -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,22 +74,154 @@ 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,
|
|
89
90
|
control_type_t parent_type
|
|
90
91
|
);
|
|
91
92
|
|
|
93
|
+
typedef struct {
|
|
94
|
+
control_type_t type;
|
|
95
|
+
uint32_t offset;
|
|
96
|
+
bool found;
|
|
97
|
+
} earliest_control_keyword_t;
|
|
98
|
+
|
|
99
|
+
typedef struct {
|
|
100
|
+
earliest_control_keyword_t* result;
|
|
101
|
+
const uint8_t* source_start;
|
|
102
|
+
} location_walker_context_t;
|
|
103
|
+
|
|
104
|
+
static bool find_earliest_control_keyword_walker(const pm_node_t* node, void* data) {
|
|
105
|
+
if (!node) { return true; }
|
|
106
|
+
|
|
107
|
+
location_walker_context_t* context = (location_walker_context_t*) data;
|
|
108
|
+
earliest_control_keyword_t* result = context->result;
|
|
109
|
+
|
|
110
|
+
control_type_t current_type = CONTROL_TYPE_UNKNOWN;
|
|
111
|
+
uint32_t keyword_offset = UINT32_MAX;
|
|
112
|
+
|
|
113
|
+
switch (node->type) {
|
|
114
|
+
case PM_IF_NODE: {
|
|
115
|
+
pm_if_node_t* if_node = (pm_if_node_t*) node;
|
|
116
|
+
current_type = CONTROL_TYPE_IF;
|
|
117
|
+
keyword_offset = (uint32_t) (if_node->if_keyword_loc.start - context->source_start);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
case PM_UNLESS_NODE: {
|
|
122
|
+
pm_unless_node_t* unless_node = (pm_unless_node_t*) node;
|
|
123
|
+
current_type = CONTROL_TYPE_UNLESS;
|
|
124
|
+
keyword_offset = (uint32_t) (unless_node->keyword_loc.start - context->source_start);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
case PM_CASE_NODE: {
|
|
129
|
+
pm_case_node_t* case_node = (pm_case_node_t*) node;
|
|
130
|
+
current_type = CONTROL_TYPE_CASE;
|
|
131
|
+
keyword_offset = (uint32_t) (case_node->case_keyword_loc.start - context->source_start);
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
case PM_CASE_MATCH_NODE: {
|
|
136
|
+
pm_case_match_node_t* case_match_node = (pm_case_match_node_t*) node;
|
|
137
|
+
current_type = CONTROL_TYPE_CASE_MATCH;
|
|
138
|
+
keyword_offset = (uint32_t) (case_match_node->case_keyword_loc.start - context->source_start);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
case PM_WHILE_NODE: {
|
|
143
|
+
pm_while_node_t* while_node = (pm_while_node_t*) node;
|
|
144
|
+
current_type = CONTROL_TYPE_WHILE;
|
|
145
|
+
keyword_offset = (uint32_t) (while_node->keyword_loc.start - context->source_start);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
case PM_UNTIL_NODE: {
|
|
150
|
+
pm_until_node_t* until_node = (pm_until_node_t*) node;
|
|
151
|
+
current_type = CONTROL_TYPE_UNTIL;
|
|
152
|
+
keyword_offset = (uint32_t) (until_node->keyword_loc.start - context->source_start);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
case PM_FOR_NODE: {
|
|
157
|
+
pm_for_node_t* for_node = (pm_for_node_t*) node;
|
|
158
|
+
current_type = CONTROL_TYPE_FOR;
|
|
159
|
+
keyword_offset = (uint32_t) (for_node->for_keyword_loc.start - context->source_start);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
case PM_BEGIN_NODE: {
|
|
164
|
+
pm_begin_node_t* begin_node = (pm_begin_node_t*) node;
|
|
165
|
+
current_type = CONTROL_TYPE_BEGIN;
|
|
166
|
+
|
|
167
|
+
if (begin_node->begin_keyword_loc.start != NULL) {
|
|
168
|
+
keyword_offset = (uint32_t) (begin_node->begin_keyword_loc.start - context->source_start);
|
|
169
|
+
} else {
|
|
170
|
+
keyword_offset = (uint32_t) (node->location.start - context->source_start);
|
|
171
|
+
}
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
case PM_YIELD_NODE: {
|
|
176
|
+
current_type = CONTROL_TYPE_YIELD;
|
|
177
|
+
keyword_offset = (uint32_t) (node->location.start - context->source_start);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
case PM_CALL_NODE: {
|
|
182
|
+
pm_call_node_t* call = (pm_call_node_t*) node;
|
|
183
|
+
|
|
184
|
+
if (call->block != NULL) {
|
|
185
|
+
current_type = CONTROL_TYPE_BLOCK;
|
|
186
|
+
keyword_offset = (uint32_t) (node->location.start - context->source_start);
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
case PM_NEXT_NODE:
|
|
192
|
+
case PM_BREAK_NODE:
|
|
193
|
+
case PM_RETURN_NODE: {
|
|
194
|
+
current_type = CONTROL_TYPE_UNKNOWN;
|
|
195
|
+
keyword_offset = (uint32_t) (node->location.start - context->source_start);
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
default: break;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (keyword_offset != UINT32_MAX) {
|
|
203
|
+
if (!result->found || keyword_offset < result->offset) {
|
|
204
|
+
result->type = current_type;
|
|
205
|
+
result->offset = keyword_offset;
|
|
206
|
+
result->found = true;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static control_type_t find_earliest_control_keyword(pm_node_t* root, const uint8_t* source_start) {
|
|
214
|
+
if (!root) { return CONTROL_TYPE_UNKNOWN; }
|
|
215
|
+
|
|
216
|
+
earliest_control_keyword_t result = { .type = CONTROL_TYPE_UNKNOWN, .offset = UINT32_MAX, .found = false };
|
|
217
|
+
|
|
218
|
+
location_walker_context_t context = { .result = &result, .source_start = source_start };
|
|
219
|
+
|
|
220
|
+
pm_visit_node(root, find_earliest_control_keyword_walker, &context);
|
|
221
|
+
|
|
222
|
+
return result.found ? result.type : CONTROL_TYPE_UNKNOWN;
|
|
223
|
+
}
|
|
224
|
+
|
|
92
225
|
static control_type_t detect_control_type(AST_ERB_CONTENT_NODE_T* erb_node) {
|
|
93
226
|
if (!erb_node || erb_node->base.type != AST_ERB_CONTENT_NODE) { return CONTROL_TYPE_UNKNOWN; }
|
|
94
227
|
|
|
@@ -98,26 +231,18 @@ static control_type_t detect_control_type(AST_ERB_CONTENT_NODE_T* erb_node) {
|
|
|
98
231
|
|
|
99
232
|
if (ruby->valid) { return CONTROL_TYPE_UNKNOWN; }
|
|
100
233
|
|
|
101
|
-
|
|
102
|
-
|
|
234
|
+
pm_node_t* root = ruby->root;
|
|
235
|
+
|
|
103
236
|
if (has_elsif_node(ruby)) { return CONTROL_TYPE_ELSIF; }
|
|
104
237
|
if (has_else_node(ruby)) { return CONTROL_TYPE_ELSE; }
|
|
105
238
|
if (has_end(ruby)) { return CONTROL_TYPE_END; }
|
|
106
|
-
if (has_case_node(ruby)) { return CONTROL_TYPE_CASE; }
|
|
107
|
-
if (has_case_match_node(ruby)) { return CONTROL_TYPE_CASE_MATCH; }
|
|
108
239
|
if (has_when_node(ruby)) { return CONTROL_TYPE_WHEN; }
|
|
109
240
|
if (has_in_node(ruby)) { return CONTROL_TYPE_IN; }
|
|
110
|
-
if (has_begin_node(ruby)) { return CONTROL_TYPE_BEGIN; }
|
|
111
241
|
if (has_rescue_node(ruby)) { return CONTROL_TYPE_RESCUE; }
|
|
112
242
|
if (has_ensure_node(ruby)) { return CONTROL_TYPE_ENSURE; }
|
|
113
|
-
if (has_unless_node(ruby)) { return CONTROL_TYPE_UNLESS; }
|
|
114
|
-
if (has_while_node(ruby)) { return CONTROL_TYPE_WHILE; }
|
|
115
|
-
if (has_until_node(ruby)) { return CONTROL_TYPE_UNTIL; }
|
|
116
|
-
if (has_for_node(ruby)) { return CONTROL_TYPE_FOR; }
|
|
117
243
|
if (has_block_closing(ruby)) { return CONTROL_TYPE_BLOCK_CLOSE; }
|
|
118
|
-
if (has_yield_node(ruby)) { return CONTROL_TYPE_YIELD; }
|
|
119
244
|
|
|
120
|
-
return
|
|
245
|
+
return find_earliest_control_keyword(root, ruby->parser.start);
|
|
121
246
|
}
|
|
122
247
|
|
|
123
248
|
static bool is_subsequent_type(control_type_t parent_type, control_type_t child_type) {
|
|
@@ -149,19 +274,21 @@ static bool is_terminator_type(control_type_t parent_type, control_type_t child_
|
|
|
149
274
|
|
|
150
275
|
static AST_NODE_T* create_control_node(
|
|
151
276
|
AST_ERB_CONTENT_NODE_T* erb_node,
|
|
152
|
-
|
|
277
|
+
hb_array_T* children,
|
|
153
278
|
AST_NODE_T* subsequent,
|
|
154
279
|
AST_ERB_END_NODE_T* end_node,
|
|
155
280
|
control_type_t control_type
|
|
156
281
|
) {
|
|
157
|
-
|
|
282
|
+
hb_array_T* errors = erb_node->base.errors;
|
|
283
|
+
erb_node->base.errors = NULL;
|
|
284
|
+
|
|
158
285
|
position_T start_position = erb_node->tag_opening->location.start;
|
|
159
286
|
position_T end_position = erb_node->tag_closing->location.end;
|
|
160
287
|
|
|
161
288
|
if (end_node) {
|
|
162
289
|
end_position = end_node->base.location.end;
|
|
163
|
-
} else if (children &&
|
|
164
|
-
AST_NODE_T* last_child =
|
|
290
|
+
} else if (children && hb_array_size(children) > 0) {
|
|
291
|
+
AST_NODE_T* last_child = hb_array_get(children, hb_array_size(children) - 1);
|
|
165
292
|
end_position = last_child->location.end;
|
|
166
293
|
} else if (subsequent) {
|
|
167
294
|
end_position = subsequent->location.end;
|
|
@@ -173,7 +300,7 @@ static AST_NODE_T* create_control_node(
|
|
|
173
300
|
|
|
174
301
|
switch (control_type) {
|
|
175
302
|
case CONTROL_TYPE_IF:
|
|
176
|
-
case CONTROL_TYPE_ELSIF:
|
|
303
|
+
case CONTROL_TYPE_ELSIF: {
|
|
177
304
|
return (AST_NODE_T*) ast_erb_if_node_init(
|
|
178
305
|
tag_opening,
|
|
179
306
|
content,
|
|
@@ -185,32 +312,40 @@ static AST_NODE_T* create_control_node(
|
|
|
185
312
|
end_position,
|
|
186
313
|
errors
|
|
187
314
|
);
|
|
315
|
+
}
|
|
188
316
|
|
|
189
|
-
case CONTROL_TYPE_ELSE:
|
|
190
|
-
return (
|
|
191
|
-
|
|
317
|
+
case CONTROL_TYPE_ELSE: {
|
|
318
|
+
return (
|
|
319
|
+
AST_NODE_T*
|
|
320
|
+
) ast_erb_else_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
321
|
+
}
|
|
192
322
|
|
|
193
323
|
case CONTROL_TYPE_CASE:
|
|
194
324
|
case CONTROL_TYPE_CASE_MATCH: {
|
|
195
325
|
AST_ERB_ELSE_NODE_T* else_node = NULL;
|
|
196
326
|
if (subsequent && subsequent->type == AST_ERB_ELSE_NODE) { else_node = (AST_ERB_ELSE_NODE_T*) subsequent; }
|
|
197
327
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
328
|
+
hb_array_T* when_conditions = hb_array_init(8);
|
|
329
|
+
hb_array_T* in_conditions = hb_array_init(8);
|
|
330
|
+
hb_array_T* non_when_non_in_children = hb_array_init(8);
|
|
331
|
+
|
|
332
|
+
for (size_t i = 0; i < hb_array_size(children); i++) {
|
|
333
|
+
AST_NODE_T* child = hb_array_get(children, i);
|
|
201
334
|
|
|
202
|
-
for (size_t i = 0; i < array_size(children); i++) {
|
|
203
|
-
AST_NODE_T* child = array_get(children, i);
|
|
204
335
|
if (child && child->type == AST_ERB_WHEN_NODE) {
|
|
205
|
-
|
|
336
|
+
hb_array_append(when_conditions, child);
|
|
206
337
|
} else if (child && child->type == AST_ERB_IN_NODE) {
|
|
207
|
-
|
|
338
|
+
hb_array_append(in_conditions, child);
|
|
208
339
|
} else {
|
|
209
|
-
|
|
340
|
+
hb_array_append(non_when_non_in_children, child);
|
|
210
341
|
}
|
|
211
342
|
}
|
|
212
343
|
|
|
213
|
-
|
|
344
|
+
hb_array_free(&children);
|
|
345
|
+
|
|
346
|
+
if (hb_array_size(in_conditions) > 0) {
|
|
347
|
+
hb_array_free(&when_conditions);
|
|
348
|
+
|
|
214
349
|
return (AST_NODE_T*) ast_erb_case_match_node_init(
|
|
215
350
|
tag_opening,
|
|
216
351
|
content,
|
|
@@ -223,30 +358,34 @@ static AST_NODE_T* create_control_node(
|
|
|
223
358
|
end_position,
|
|
224
359
|
errors
|
|
225
360
|
);
|
|
226
|
-
}
|
|
361
|
+
} else {
|
|
362
|
+
hb_array_free(&in_conditions);
|
|
227
363
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
364
|
+
return (AST_NODE_T*) ast_erb_case_node_init(
|
|
365
|
+
tag_opening,
|
|
366
|
+
content,
|
|
367
|
+
tag_closing,
|
|
368
|
+
non_when_non_in_children,
|
|
369
|
+
when_conditions,
|
|
370
|
+
else_node,
|
|
371
|
+
end_node,
|
|
372
|
+
start_position,
|
|
373
|
+
end_position,
|
|
374
|
+
errors
|
|
375
|
+
);
|
|
376
|
+
}
|
|
240
377
|
}
|
|
241
378
|
|
|
242
379
|
case CONTROL_TYPE_WHEN: {
|
|
243
|
-
return (
|
|
244
|
-
|
|
380
|
+
return (
|
|
381
|
+
AST_NODE_T*
|
|
382
|
+
) ast_erb_when_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
245
383
|
}
|
|
246
384
|
|
|
247
385
|
case CONTROL_TYPE_IN: {
|
|
248
|
-
return (
|
|
249
|
-
|
|
386
|
+
return (
|
|
387
|
+
AST_NODE_T*
|
|
388
|
+
) ast_erb_in_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
250
389
|
}
|
|
251
390
|
|
|
252
391
|
case CONTROL_TYPE_BEGIN: {
|
|
@@ -297,8 +436,9 @@ static AST_NODE_T* create_control_node(
|
|
|
297
436
|
}
|
|
298
437
|
|
|
299
438
|
case CONTROL_TYPE_ENSURE: {
|
|
300
|
-
return (
|
|
301
|
-
|
|
439
|
+
return (
|
|
440
|
+
AST_NODE_T*
|
|
441
|
+
) ast_erb_ensure_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
302
442
|
}
|
|
303
443
|
|
|
304
444
|
case CONTROL_TYPE_UNLESS: {
|
|
@@ -372,34 +512,35 @@ static AST_NODE_T* create_control_node(
|
|
|
372
512
|
}
|
|
373
513
|
|
|
374
514
|
case CONTROL_TYPE_YIELD: {
|
|
375
|
-
return (
|
|
376
|
-
|
|
515
|
+
return (
|
|
516
|
+
AST_NODE_T*
|
|
517
|
+
) ast_erb_yield_node_init(tag_opening, content, tag_closing, start_position, end_position, errors);
|
|
377
518
|
}
|
|
378
519
|
|
|
379
|
-
default:
|
|
520
|
+
default: return NULL;
|
|
380
521
|
}
|
|
381
522
|
}
|
|
382
523
|
|
|
383
524
|
static size_t process_control_structure(
|
|
384
525
|
AST_NODE_T* node,
|
|
385
|
-
|
|
526
|
+
hb_array_T* array,
|
|
386
527
|
size_t index,
|
|
387
|
-
|
|
528
|
+
hb_array_T* output_array,
|
|
388
529
|
analyze_ruby_context_T* context,
|
|
389
530
|
control_type_t initial_type
|
|
390
531
|
) {
|
|
391
|
-
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*)
|
|
392
|
-
|
|
532
|
+
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*) hb_array_get(array, index);
|
|
533
|
+
hb_array_T* children = hb_array_init(8);
|
|
393
534
|
|
|
394
535
|
index++;
|
|
395
536
|
|
|
396
537
|
if (initial_type == CONTROL_TYPE_CASE || initial_type == CONTROL_TYPE_CASE_MATCH) {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
538
|
+
hb_array_T* when_conditions = hb_array_init(8);
|
|
539
|
+
hb_array_T* in_conditions = hb_array_init(8);
|
|
540
|
+
hb_array_T* non_when_non_in_children = hb_array_init(8);
|
|
400
541
|
|
|
401
|
-
while (index <
|
|
402
|
-
AST_NODE_T* next_node =
|
|
542
|
+
while (index < hb_array_size(array)) {
|
|
543
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
403
544
|
|
|
404
545
|
if (!next_node) { break; }
|
|
405
546
|
|
|
@@ -410,17 +551,17 @@ static size_t process_control_structure(
|
|
|
410
551
|
if (next_type == CONTROL_TYPE_WHEN || next_type == CONTROL_TYPE_IN) { break; }
|
|
411
552
|
}
|
|
412
553
|
|
|
413
|
-
|
|
554
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
414
555
|
index++;
|
|
415
556
|
}
|
|
416
557
|
|
|
417
|
-
while (index <
|
|
418
|
-
AST_NODE_T* next_node =
|
|
558
|
+
while (index < hb_array_size(array)) {
|
|
559
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
419
560
|
|
|
420
561
|
if (!next_node) { break; }
|
|
421
562
|
|
|
422
563
|
if (next_node->type != AST_ERB_CONTENT_NODE) {
|
|
423
|
-
|
|
564
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
424
565
|
index++;
|
|
425
566
|
continue;
|
|
426
567
|
}
|
|
@@ -429,11 +570,14 @@ static size_t process_control_structure(
|
|
|
429
570
|
control_type_t next_type = detect_control_type(erb_content);
|
|
430
571
|
|
|
431
572
|
if (next_type == CONTROL_TYPE_WHEN) {
|
|
432
|
-
|
|
573
|
+
hb_array_T* when_statements = hb_array_init(8);
|
|
433
574
|
index++;
|
|
434
575
|
|
|
435
576
|
index = process_block_children(node, array, index, when_statements, context, CONTROL_TYPE_WHEN);
|
|
436
577
|
|
|
578
|
+
hb_array_T* when_errors = erb_content->base.errors;
|
|
579
|
+
erb_content->base.errors = NULL;
|
|
580
|
+
|
|
437
581
|
AST_ERB_WHEN_NODE_T* when_node = ast_erb_when_node_init(
|
|
438
582
|
erb_content->tag_opening,
|
|
439
583
|
erb_content->content,
|
|
@@ -441,18 +585,23 @@ static size_t process_control_structure(
|
|
|
441
585
|
when_statements,
|
|
442
586
|
erb_content->tag_opening->location.start,
|
|
443
587
|
erb_content->tag_closing->location.end,
|
|
444
|
-
|
|
588
|
+
when_errors
|
|
445
589
|
);
|
|
446
590
|
|
|
447
|
-
|
|
591
|
+
ast_node_free((AST_NODE_T*) erb_content);
|
|
592
|
+
|
|
593
|
+
hb_array_append(when_conditions, (AST_NODE_T*) when_node);
|
|
448
594
|
|
|
449
595
|
continue;
|
|
450
596
|
} else if (next_type == CONTROL_TYPE_IN) {
|
|
451
|
-
|
|
597
|
+
hb_array_T* in_statements = hb_array_init(8);
|
|
452
598
|
index++;
|
|
453
599
|
|
|
454
600
|
index = process_block_children(node, array, index, in_statements, context, CONTROL_TYPE_IN);
|
|
455
601
|
|
|
602
|
+
hb_array_T* in_errors = erb_content->base.errors;
|
|
603
|
+
erb_content->base.errors = NULL;
|
|
604
|
+
|
|
456
605
|
AST_ERB_IN_NODE_T* in_node = ast_erb_in_node_init(
|
|
457
606
|
erb_content->tag_opening,
|
|
458
607
|
erb_content->content,
|
|
@@ -460,49 +609,40 @@ static size_t process_control_structure(
|
|
|
460
609
|
in_statements,
|
|
461
610
|
erb_content->tag_opening->location.start,
|
|
462
611
|
erb_content->tag_closing->location.end,
|
|
463
|
-
|
|
612
|
+
in_errors
|
|
464
613
|
);
|
|
465
614
|
|
|
466
|
-
|
|
615
|
+
ast_node_free((AST_NODE_T*) erb_content);
|
|
616
|
+
|
|
617
|
+
hb_array_append(in_conditions, (AST_NODE_T*) in_node);
|
|
467
618
|
|
|
468
619
|
continue;
|
|
469
620
|
} else if (next_type == CONTROL_TYPE_ELSE || next_type == CONTROL_TYPE_END) {
|
|
470
621
|
break;
|
|
471
622
|
} else {
|
|
472
|
-
|
|
623
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
473
624
|
index++;
|
|
474
625
|
}
|
|
475
626
|
}
|
|
476
627
|
|
|
477
628
|
AST_ERB_ELSE_NODE_T* else_clause = NULL;
|
|
478
629
|
|
|
479
|
-
if (index <
|
|
480
|
-
AST_NODE_T* next_node =
|
|
630
|
+
if (index < hb_array_size(array)) {
|
|
631
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
481
632
|
|
|
482
633
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
483
634
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
484
635
|
control_type_t next_type = detect_control_type(next_erb);
|
|
485
636
|
|
|
486
637
|
if (next_type == CONTROL_TYPE_ELSE) {
|
|
487
|
-
|
|
638
|
+
hb_array_T* else_children = hb_array_init(8);
|
|
488
639
|
|
|
489
640
|
index++;
|
|
490
641
|
|
|
491
|
-
|
|
492
|
-
AST_NODE_T* child = array_get(array, index);
|
|
493
|
-
|
|
494
|
-
if (!child) { break; }
|
|
495
|
-
|
|
496
|
-
if (child->type == AST_ERB_CONTENT_NODE) {
|
|
497
|
-
AST_ERB_CONTENT_NODE_T* child_erb = (AST_ERB_CONTENT_NODE_T*) child;
|
|
498
|
-
control_type_t child_type = detect_control_type(child_erb);
|
|
499
|
-
|
|
500
|
-
if (child_type == CONTROL_TYPE_END) { break; }
|
|
501
|
-
}
|
|
642
|
+
index = process_block_children(node, array, index, else_children, context, initial_type);
|
|
502
643
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
}
|
|
644
|
+
hb_array_T* else_errors = next_erb->base.errors;
|
|
645
|
+
next_erb->base.errors = NULL;
|
|
506
646
|
|
|
507
647
|
else_clause = ast_erb_else_node_init(
|
|
508
648
|
next_erb->tag_opening,
|
|
@@ -511,30 +651,37 @@ static size_t process_control_structure(
|
|
|
511
651
|
else_children,
|
|
512
652
|
next_erb->tag_opening->location.start,
|
|
513
653
|
next_erb->tag_closing->location.end,
|
|
514
|
-
|
|
654
|
+
else_errors
|
|
515
655
|
);
|
|
656
|
+
|
|
657
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
516
658
|
}
|
|
517
659
|
}
|
|
518
660
|
}
|
|
519
661
|
|
|
520
662
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
521
663
|
|
|
522
|
-
if (index <
|
|
523
|
-
AST_NODE_T* potential_end =
|
|
664
|
+
if (index < hb_array_size(array)) {
|
|
665
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
524
666
|
|
|
525
667
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
526
668
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
527
669
|
|
|
528
670
|
if (detect_control_type(end_erb) == CONTROL_TYPE_END) {
|
|
671
|
+
hb_array_T* end_errors = end_erb->base.errors;
|
|
672
|
+
end_erb->base.errors = NULL;
|
|
673
|
+
|
|
529
674
|
end_node = ast_erb_end_node_init(
|
|
530
675
|
end_erb->tag_opening,
|
|
531
676
|
end_erb->content,
|
|
532
677
|
end_erb->tag_closing,
|
|
533
678
|
end_erb->tag_opening->location.start,
|
|
534
679
|
end_erb->tag_closing->location.end,
|
|
535
|
-
|
|
680
|
+
end_errors
|
|
536
681
|
);
|
|
537
682
|
|
|
683
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
684
|
+
|
|
538
685
|
index++;
|
|
539
686
|
}
|
|
540
687
|
}
|
|
@@ -547,15 +694,18 @@ static size_t process_control_structure(
|
|
|
547
694
|
end_position = end_node->base.location.end;
|
|
548
695
|
} else if (else_clause) {
|
|
549
696
|
end_position = else_clause->base.location.end;
|
|
550
|
-
} else if (
|
|
551
|
-
AST_NODE_T* last_when =
|
|
697
|
+
} else if (hb_array_size(when_conditions) > 0) {
|
|
698
|
+
AST_NODE_T* last_when = hb_array_get(when_conditions, hb_array_size(when_conditions) - 1);
|
|
552
699
|
end_position = last_when->location.end;
|
|
553
|
-
} else if (
|
|
554
|
-
AST_NODE_T* last_in =
|
|
700
|
+
} else if (hb_array_size(in_conditions) > 0) {
|
|
701
|
+
AST_NODE_T* last_in = hb_array_get(in_conditions, hb_array_size(in_conditions) - 1);
|
|
555
702
|
end_position = last_in->location.end;
|
|
556
703
|
}
|
|
557
704
|
|
|
558
|
-
if (
|
|
705
|
+
if (hb_array_size(in_conditions) > 0) {
|
|
706
|
+
hb_array_T* case_match_errors = erb_node->base.errors;
|
|
707
|
+
erb_node->base.errors = NULL;
|
|
708
|
+
|
|
559
709
|
AST_ERB_CASE_MATCH_NODE_T* case_match_node = ast_erb_case_match_node_init(
|
|
560
710
|
erb_node->tag_opening,
|
|
561
711
|
erb_node->content,
|
|
@@ -566,13 +716,21 @@ static size_t process_control_structure(
|
|
|
566
716
|
end_node,
|
|
567
717
|
start_position,
|
|
568
718
|
end_position,
|
|
569
|
-
|
|
719
|
+
case_match_errors
|
|
570
720
|
);
|
|
571
721
|
|
|
572
|
-
|
|
722
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
723
|
+
|
|
724
|
+
hb_array_append(output_array, (AST_NODE_T*) case_match_node);
|
|
725
|
+
hb_array_free(&when_conditions);
|
|
726
|
+
hb_array_free(&children);
|
|
727
|
+
|
|
573
728
|
return index;
|
|
574
729
|
}
|
|
575
730
|
|
|
731
|
+
hb_array_T* case_errors = erb_node->base.errors;
|
|
732
|
+
erb_node->base.errors = NULL;
|
|
733
|
+
|
|
576
734
|
AST_ERB_CASE_NODE_T* case_node = ast_erb_case_node_init(
|
|
577
735
|
erb_node->tag_opening,
|
|
578
736
|
erb_node->content,
|
|
@@ -583,10 +741,15 @@ static size_t process_control_structure(
|
|
|
583
741
|
end_node,
|
|
584
742
|
start_position,
|
|
585
743
|
end_position,
|
|
586
|
-
|
|
744
|
+
case_errors
|
|
587
745
|
);
|
|
588
746
|
|
|
589
|
-
|
|
747
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
748
|
+
|
|
749
|
+
hb_array_append(output_array, (AST_NODE_T*) case_node);
|
|
750
|
+
hb_array_free(&in_conditions);
|
|
751
|
+
hb_array_free(&children);
|
|
752
|
+
|
|
590
753
|
return index;
|
|
591
754
|
}
|
|
592
755
|
|
|
@@ -597,8 +760,8 @@ static size_t process_control_structure(
|
|
|
597
760
|
AST_ERB_ELSE_NODE_T* else_clause = NULL;
|
|
598
761
|
AST_ERB_ENSURE_NODE_T* ensure_clause = NULL;
|
|
599
762
|
|
|
600
|
-
if (index <
|
|
601
|
-
AST_NODE_T* next_node =
|
|
763
|
+
if (index < hb_array_size(array)) {
|
|
764
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
602
765
|
|
|
603
766
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
604
767
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -612,33 +775,22 @@ static size_t process_control_structure(
|
|
|
612
775
|
}
|
|
613
776
|
}
|
|
614
777
|
|
|
615
|
-
if (index <
|
|
616
|
-
AST_NODE_T* next_node =
|
|
778
|
+
if (index < hb_array_size(array)) {
|
|
779
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
617
780
|
|
|
618
781
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
619
782
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
620
783
|
control_type_t next_type = detect_control_type(next_erb);
|
|
621
784
|
|
|
622
785
|
if (next_type == CONTROL_TYPE_ELSE) {
|
|
623
|
-
|
|
786
|
+
hb_array_T* else_children = hb_array_init(8);
|
|
624
787
|
|
|
625
788
|
index++;
|
|
626
789
|
|
|
627
|
-
|
|
628
|
-
AST_NODE_T* child = array_get(array, index);
|
|
790
|
+
index = process_block_children(node, array, index, else_children, context, initial_type);
|
|
629
791
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
if (child->type == AST_ERB_CONTENT_NODE) {
|
|
633
|
-
AST_ERB_CONTENT_NODE_T* child_erb = (AST_ERB_CONTENT_NODE_T*) child;
|
|
634
|
-
control_type_t child_type = detect_control_type(child_erb);
|
|
635
|
-
|
|
636
|
-
if (child_type == CONTROL_TYPE_ENSURE || child_type == CONTROL_TYPE_END) { break; }
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
array_append(else_children, child);
|
|
640
|
-
index++;
|
|
641
|
-
}
|
|
792
|
+
hb_array_T* else_errors = next_erb->base.errors;
|
|
793
|
+
next_erb->base.errors = NULL;
|
|
642
794
|
|
|
643
795
|
else_clause = ast_erb_else_node_init(
|
|
644
796
|
next_erb->tag_opening,
|
|
@@ -647,26 +799,28 @@ static size_t process_control_structure(
|
|
|
647
799
|
else_children,
|
|
648
800
|
next_erb->tag_opening->location.start,
|
|
649
801
|
next_erb->tag_closing->location.end,
|
|
650
|
-
|
|
802
|
+
else_errors
|
|
651
803
|
);
|
|
804
|
+
|
|
805
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
652
806
|
}
|
|
653
807
|
}
|
|
654
808
|
}
|
|
655
809
|
|
|
656
|
-
if (index <
|
|
657
|
-
AST_NODE_T* next_node =
|
|
810
|
+
if (index < hb_array_size(array)) {
|
|
811
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
658
812
|
|
|
659
813
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
660
814
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
661
815
|
control_type_t next_type = detect_control_type(next_erb);
|
|
662
816
|
|
|
663
817
|
if (next_type == CONTROL_TYPE_ENSURE) {
|
|
664
|
-
|
|
818
|
+
hb_array_T* ensure_children = hb_array_init(8);
|
|
665
819
|
|
|
666
820
|
index++;
|
|
667
821
|
|
|
668
|
-
while (index <
|
|
669
|
-
AST_NODE_T* child =
|
|
822
|
+
while (index < hb_array_size(array)) {
|
|
823
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
670
824
|
|
|
671
825
|
if (!child) { break; }
|
|
672
826
|
|
|
@@ -677,10 +831,13 @@ static size_t process_control_structure(
|
|
|
677
831
|
if (child_type == CONTROL_TYPE_END) { break; }
|
|
678
832
|
}
|
|
679
833
|
|
|
680
|
-
|
|
834
|
+
hb_array_append(ensure_children, child);
|
|
681
835
|
index++;
|
|
682
836
|
}
|
|
683
837
|
|
|
838
|
+
hb_array_T* ensure_errors = next_erb->base.errors;
|
|
839
|
+
next_erb->base.errors = NULL;
|
|
840
|
+
|
|
684
841
|
ensure_clause = ast_erb_ensure_node_init(
|
|
685
842
|
next_erb->tag_opening,
|
|
686
843
|
next_erb->content,
|
|
@@ -688,30 +845,37 @@ static size_t process_control_structure(
|
|
|
688
845
|
ensure_children,
|
|
689
846
|
next_erb->tag_opening->location.start,
|
|
690
847
|
next_erb->tag_closing->location.end,
|
|
691
|
-
|
|
848
|
+
ensure_errors
|
|
692
849
|
);
|
|
850
|
+
|
|
851
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
693
852
|
}
|
|
694
853
|
}
|
|
695
854
|
}
|
|
696
855
|
|
|
697
856
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
698
857
|
|
|
699
|
-
if (index <
|
|
700
|
-
AST_NODE_T* potential_end =
|
|
858
|
+
if (index < hb_array_size(array)) {
|
|
859
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
701
860
|
|
|
702
861
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
703
862
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
704
863
|
|
|
705
864
|
if (detect_control_type(end_erb) == CONTROL_TYPE_END) {
|
|
865
|
+
hb_array_T* end_errors = end_erb->base.errors;
|
|
866
|
+
end_erb->base.errors = NULL;
|
|
867
|
+
|
|
706
868
|
end_node = ast_erb_end_node_init(
|
|
707
869
|
end_erb->tag_opening,
|
|
708
870
|
end_erb->content,
|
|
709
871
|
end_erb->tag_closing,
|
|
710
872
|
end_erb->tag_opening->location.start,
|
|
711
873
|
end_erb->tag_closing->location.end,
|
|
712
|
-
|
|
874
|
+
end_errors
|
|
713
875
|
);
|
|
714
876
|
|
|
877
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
878
|
+
|
|
715
879
|
index++;
|
|
716
880
|
}
|
|
717
881
|
}
|
|
@@ -730,6 +894,9 @@ static size_t process_control_structure(
|
|
|
730
894
|
end_position = rescue_clause->base.location.end;
|
|
731
895
|
}
|
|
732
896
|
|
|
897
|
+
hb_array_T* begin_errors = erb_node->base.errors;
|
|
898
|
+
erb_node->base.errors = NULL;
|
|
899
|
+
|
|
733
900
|
AST_ERB_BEGIN_NODE_T* begin_node = ast_erb_begin_node_init(
|
|
734
901
|
erb_node->tag_opening,
|
|
735
902
|
erb_node->content,
|
|
@@ -741,10 +908,12 @@ static size_t process_control_structure(
|
|
|
741
908
|
end_node,
|
|
742
909
|
start_position,
|
|
743
910
|
end_position,
|
|
744
|
-
|
|
911
|
+
begin_errors
|
|
745
912
|
);
|
|
746
913
|
|
|
747
|
-
|
|
914
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
915
|
+
|
|
916
|
+
hb_array_append(output_array, (AST_NODE_T*) begin_node);
|
|
748
917
|
return index;
|
|
749
918
|
}
|
|
750
919
|
|
|
@@ -753,23 +922,28 @@ static size_t process_control_structure(
|
|
|
753
922
|
|
|
754
923
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
755
924
|
|
|
756
|
-
if (index <
|
|
757
|
-
AST_NODE_T* potential_close =
|
|
925
|
+
if (index < hb_array_size(array)) {
|
|
926
|
+
AST_NODE_T* potential_close = hb_array_get(array, index);
|
|
758
927
|
|
|
759
928
|
if (potential_close && potential_close->type == AST_ERB_CONTENT_NODE) {
|
|
760
929
|
AST_ERB_CONTENT_NODE_T* close_erb = (AST_ERB_CONTENT_NODE_T*) potential_close;
|
|
761
930
|
control_type_t close_type = detect_control_type(close_erb);
|
|
762
931
|
|
|
763
932
|
if (close_type == CONTROL_TYPE_BLOCK_CLOSE || close_type == CONTROL_TYPE_END) {
|
|
933
|
+
hb_array_T* end_errors = close_erb->base.errors;
|
|
934
|
+
close_erb->base.errors = NULL;
|
|
935
|
+
|
|
764
936
|
end_node = ast_erb_end_node_init(
|
|
765
937
|
close_erb->tag_opening,
|
|
766
938
|
close_erb->content,
|
|
767
939
|
close_erb->tag_closing,
|
|
768
940
|
close_erb->tag_opening->location.start,
|
|
769
941
|
close_erb->tag_closing->location.end,
|
|
770
|
-
|
|
942
|
+
end_errors
|
|
771
943
|
);
|
|
772
944
|
|
|
945
|
+
ast_node_free((AST_NODE_T*) close_erb);
|
|
946
|
+
|
|
773
947
|
index++;
|
|
774
948
|
}
|
|
775
949
|
}
|
|
@@ -780,11 +954,14 @@ static size_t process_control_structure(
|
|
|
780
954
|
|
|
781
955
|
if (end_node) {
|
|
782
956
|
end_position = end_node->base.location.end;
|
|
783
|
-
} else if (children &&
|
|
784
|
-
AST_NODE_T* last_child =
|
|
957
|
+
} else if (children && hb_array_size(children) > 0) {
|
|
958
|
+
AST_NODE_T* last_child = hb_array_get(children, hb_array_size(children) - 1);
|
|
785
959
|
end_position = last_child->location.end;
|
|
786
960
|
}
|
|
787
961
|
|
|
962
|
+
hb_array_T* block_errors = erb_node->base.errors;
|
|
963
|
+
erb_node->base.errors = NULL;
|
|
964
|
+
|
|
788
965
|
AST_ERB_BLOCK_NODE_T* block_node = ast_erb_block_node_init(
|
|
789
966
|
erb_node->tag_opening,
|
|
790
967
|
erb_node->content,
|
|
@@ -793,10 +970,12 @@ static size_t process_control_structure(
|
|
|
793
970
|
end_node,
|
|
794
971
|
start_position,
|
|
795
972
|
end_position,
|
|
796
|
-
|
|
973
|
+
block_errors
|
|
797
974
|
);
|
|
798
975
|
|
|
799
|
-
|
|
976
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
977
|
+
|
|
978
|
+
hb_array_append(output_array, (AST_NODE_T*) block_node);
|
|
800
979
|
return index;
|
|
801
980
|
}
|
|
802
981
|
|
|
@@ -805,8 +984,8 @@ static size_t process_control_structure(
|
|
|
805
984
|
AST_NODE_T* subsequent = NULL;
|
|
806
985
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
807
986
|
|
|
808
|
-
if (index <
|
|
809
|
-
AST_NODE_T* next_node =
|
|
987
|
+
if (index < hb_array_size(array)) {
|
|
988
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
810
989
|
|
|
811
990
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
812
991
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -818,22 +997,27 @@ static size_t process_control_structure(
|
|
|
818
997
|
}
|
|
819
998
|
}
|
|
820
999
|
|
|
821
|
-
if (index <
|
|
822
|
-
AST_NODE_T* potential_end =
|
|
1000
|
+
if (index < hb_array_size(array)) {
|
|
1001
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
823
1002
|
|
|
824
1003
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
825
1004
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
826
1005
|
|
|
827
1006
|
if (detect_control_type(end_erb) == CONTROL_TYPE_END) {
|
|
1007
|
+
hb_array_T* end_errors = end_erb->base.errors;
|
|
1008
|
+
end_erb->base.errors = NULL;
|
|
1009
|
+
|
|
828
1010
|
end_node = ast_erb_end_node_init(
|
|
829
1011
|
end_erb->tag_opening,
|
|
830
1012
|
end_erb->content,
|
|
831
1013
|
end_erb->tag_closing,
|
|
832
1014
|
end_erb->tag_opening->location.start,
|
|
833
1015
|
end_erb->tag_closing->location.end,
|
|
834
|
-
|
|
1016
|
+
end_errors
|
|
835
1017
|
);
|
|
836
1018
|
|
|
1019
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
1020
|
+
|
|
837
1021
|
index++;
|
|
838
1022
|
}
|
|
839
1023
|
}
|
|
@@ -841,22 +1025,27 @@ static size_t process_control_structure(
|
|
|
841
1025
|
|
|
842
1026
|
AST_NODE_T* control_node = create_control_node(erb_node, children, subsequent, end_node, initial_type);
|
|
843
1027
|
|
|
844
|
-
if (control_node) {
|
|
1028
|
+
if (control_node) {
|
|
1029
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
1030
|
+
hb_array_append(output_array, control_node);
|
|
1031
|
+
} else {
|
|
1032
|
+
hb_array_free(&children);
|
|
1033
|
+
}
|
|
845
1034
|
|
|
846
1035
|
return index;
|
|
847
1036
|
}
|
|
848
1037
|
|
|
849
1038
|
static size_t process_subsequent_block(
|
|
850
1039
|
AST_NODE_T* node,
|
|
851
|
-
|
|
1040
|
+
hb_array_T* array,
|
|
852
1041
|
size_t index,
|
|
853
1042
|
AST_NODE_T** subsequent_out,
|
|
854
1043
|
analyze_ruby_context_T* context,
|
|
855
1044
|
control_type_t parent_type
|
|
856
1045
|
) {
|
|
857
|
-
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*)
|
|
1046
|
+
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*) hb_array_get(array, index);
|
|
858
1047
|
control_type_t type = detect_control_type(erb_node);
|
|
859
|
-
|
|
1048
|
+
hb_array_T* children = hb_array_init(8);
|
|
860
1049
|
|
|
861
1050
|
index++;
|
|
862
1051
|
|
|
@@ -864,8 +1053,14 @@ static size_t process_subsequent_block(
|
|
|
864
1053
|
|
|
865
1054
|
AST_NODE_T* subsequent_node = create_control_node(erb_node, children, NULL, NULL, type);
|
|
866
1055
|
|
|
867
|
-
if (
|
|
868
|
-
AST_NODE_T*
|
|
1056
|
+
if (subsequent_node) {
|
|
1057
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
1058
|
+
} else {
|
|
1059
|
+
hb_array_free(&children);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
if (index < hb_array_size(array)) {
|
|
1063
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
869
1064
|
|
|
870
1065
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
871
1066
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -916,19 +1111,19 @@ static size_t process_subsequent_block(
|
|
|
916
1111
|
|
|
917
1112
|
static size_t process_block_children(
|
|
918
1113
|
AST_NODE_T* node,
|
|
919
|
-
|
|
1114
|
+
hb_array_T* array,
|
|
920
1115
|
size_t index,
|
|
921
|
-
|
|
1116
|
+
hb_array_T* children_array,
|
|
922
1117
|
analyze_ruby_context_T* context,
|
|
923
1118
|
control_type_t parent_type
|
|
924
1119
|
) {
|
|
925
|
-
while (index <
|
|
926
|
-
AST_NODE_T* child =
|
|
1120
|
+
while (index < hb_array_size(array)) {
|
|
1121
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
927
1122
|
|
|
928
1123
|
if (!child) { break; }
|
|
929
1124
|
|
|
930
1125
|
if (child->type != AST_ERB_CONTENT_NODE) {
|
|
931
|
-
|
|
1126
|
+
hb_array_append(children_array, child);
|
|
932
1127
|
index++;
|
|
933
1128
|
continue;
|
|
934
1129
|
}
|
|
@@ -941,35 +1136,35 @@ static size_t process_block_children(
|
|
|
941
1136
|
if (child_type == CONTROL_TYPE_IF || child_type == CONTROL_TYPE_CASE || child_type == CONTROL_TYPE_CASE_MATCH
|
|
942
1137
|
|| child_type == CONTROL_TYPE_BEGIN || child_type == CONTROL_TYPE_UNLESS || child_type == CONTROL_TYPE_WHILE
|
|
943
1138
|
|| child_type == CONTROL_TYPE_UNTIL || child_type == CONTROL_TYPE_FOR || child_type == CONTROL_TYPE_BLOCK) {
|
|
944
|
-
|
|
1139
|
+
hb_array_T* temp_array = hb_array_init(1);
|
|
945
1140
|
size_t new_index = process_control_structure(node, array, index, temp_array, context, child_type);
|
|
946
1141
|
|
|
947
|
-
if (
|
|
1142
|
+
if (hb_array_size(temp_array) > 0) { hb_array_append(children_array, hb_array_get(temp_array, 0)); }
|
|
948
1143
|
|
|
949
|
-
|
|
1144
|
+
hb_array_free(&temp_array);
|
|
950
1145
|
|
|
951
1146
|
index = new_index;
|
|
952
1147
|
continue;
|
|
953
1148
|
}
|
|
954
1149
|
|
|
955
|
-
|
|
1150
|
+
hb_array_append(children_array, child);
|
|
956
1151
|
index++;
|
|
957
1152
|
}
|
|
958
1153
|
|
|
959
1154
|
return index;
|
|
960
1155
|
}
|
|
961
1156
|
|
|
962
|
-
|
|
963
|
-
|
|
1157
|
+
hb_array_T* rewrite_node_array(AST_NODE_T* node, hb_array_T* array, analyze_ruby_context_T* context) {
|
|
1158
|
+
hb_array_T* new_array = hb_array_init(hb_array_size(array));
|
|
964
1159
|
size_t index = 0;
|
|
965
1160
|
|
|
966
|
-
while (index <
|
|
967
|
-
AST_NODE_T* item =
|
|
1161
|
+
while (index < hb_array_size(array)) {
|
|
1162
|
+
AST_NODE_T* item = hb_array_get(array, index);
|
|
968
1163
|
|
|
969
1164
|
if (!item) { break; }
|
|
970
1165
|
|
|
971
1166
|
if (item->type != AST_ERB_CONTENT_NODE) {
|
|
972
|
-
|
|
1167
|
+
hb_array_append(new_array, item);
|
|
973
1168
|
index++;
|
|
974
1169
|
continue;
|
|
975
1170
|
}
|
|
@@ -991,12 +1186,13 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
991
1186
|
continue;
|
|
992
1187
|
|
|
993
1188
|
case CONTROL_TYPE_YIELD: {
|
|
994
|
-
AST_NODE_T* yield_node = create_control_node(erb_node,
|
|
1189
|
+
AST_NODE_T* yield_node = create_control_node(erb_node, NULL, NULL, NULL, type);
|
|
995
1190
|
|
|
996
1191
|
if (yield_node) {
|
|
997
|
-
|
|
1192
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
1193
|
+
hb_array_append(new_array, yield_node);
|
|
998
1194
|
} else {
|
|
999
|
-
|
|
1195
|
+
hb_array_append(new_array, item);
|
|
1000
1196
|
}
|
|
1001
1197
|
|
|
1002
1198
|
index++;
|
|
@@ -1004,7 +1200,7 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
1004
1200
|
}
|
|
1005
1201
|
|
|
1006
1202
|
default:
|
|
1007
|
-
|
|
1203
|
+
hb_array_append(new_array, item);
|
|
1008
1204
|
index++;
|
|
1009
1205
|
break;
|
|
1010
1206
|
}
|
|
@@ -1013,41 +1209,178 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
1013
1209
|
return new_array;
|
|
1014
1210
|
}
|
|
1015
1211
|
|
|
1016
|
-
static bool
|
|
1017
|
-
|
|
1018
|
-
|
|
1212
|
+
static bool detect_invalid_erb_structures(const AST_NODE_T* node, void* data) {
|
|
1213
|
+
invalid_erb_context_T* context = (invalid_erb_context_T*) data;
|
|
1214
|
+
|
|
1215
|
+
if (node->type == AST_HTML_ATTRIBUTE_NAME_NODE) { return false; }
|
|
1216
|
+
|
|
1217
|
+
bool is_loop_node =
|
|
1218
|
+
(node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE || node->type == AST_ERB_FOR_NODE
|
|
1219
|
+
|| node->type == AST_ERB_BLOCK_NODE);
|
|
1220
|
+
|
|
1221
|
+
bool is_begin_node = (node->type == AST_ERB_BEGIN_NODE);
|
|
1222
|
+
|
|
1223
|
+
if (is_loop_node) { context->loop_depth++; }
|
|
1224
|
+
|
|
1225
|
+
if (is_begin_node) { context->rescue_depth++; }
|
|
1226
|
+
|
|
1227
|
+
if (node->type == AST_ERB_CONTENT_NODE) {
|
|
1228
|
+
const AST_ERB_CONTENT_NODE_T* content_node = (const AST_ERB_CONTENT_NODE_T*) node;
|
|
1229
|
+
|
|
1230
|
+
if (content_node->parsed && !content_node->valid && content_node->analyzed_ruby != NULL) {
|
|
1231
|
+
analyzed_ruby_T* analyzed = content_node->analyzed_ruby;
|
|
1232
|
+
|
|
1233
|
+
// =begin
|
|
1234
|
+
if (has_error_message(analyzed, "embedded document meets end of file")) {
|
|
1235
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1236
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1237
|
+
|
|
1238
|
+
return true;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
// =end
|
|
1242
|
+
if (has_error_message(analyzed, "unexpected '=', ignoring it")
|
|
1243
|
+
&& has_error_message(analyzed, "unexpected 'end', ignoring it")) {
|
|
1244
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1245
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1246
|
+
|
|
1247
|
+
return true;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
const char* keyword = NULL;
|
|
1251
|
+
|
|
1252
|
+
if (context->loop_depth == 0) {
|
|
1253
|
+
if (has_error_message(analyzed, "Invalid break")) {
|
|
1254
|
+
keyword = "`<% break %>`";
|
|
1255
|
+
} else if (has_error_message(analyzed, "Invalid next")) {
|
|
1256
|
+
keyword = "`<% next %>`";
|
|
1257
|
+
} else if (has_error_message(analyzed, "Invalid redo")) {
|
|
1258
|
+
keyword = "`<% redo %>`";
|
|
1259
|
+
}
|
|
1260
|
+
} else {
|
|
1261
|
+
if (has_error_message(analyzed, "Invalid redo") || has_error_message(analyzed, "Invalid break")
|
|
1262
|
+
|| has_error_message(analyzed, "Invalid next")) {
|
|
1263
|
+
|
|
1264
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1265
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1266
|
+
|
|
1267
|
+
return true;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1019
1270
|
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1271
|
+
if (context->rescue_depth == 0) {
|
|
1272
|
+
if (has_error_message(analyzed, "Invalid retry without rescue")) { keyword = "`<% retry %>`"; }
|
|
1273
|
+
} else {
|
|
1274
|
+
if (has_error_message(analyzed, "Invalid retry without rescue")) {
|
|
1275
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1276
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1277
|
+
|
|
1278
|
+
return true;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
if (keyword == NULL) { keyword = erb_keyword_from_analyzed_ruby(analyzed); }
|
|
1283
|
+
|
|
1284
|
+
if (keyword != NULL && !token_value_empty(content_node->tag_closing)) {
|
|
1285
|
+
append_erb_control_flow_scope_error(keyword, node->location.start, node->location.end, node->errors);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
if (node->type == AST_ERB_IF_NODE) {
|
|
1291
|
+
const AST_ERB_IF_NODE_T* if_node = (const AST_ERB_IF_NODE_T*) node;
|
|
1292
|
+
|
|
1293
|
+
if (if_node->end_node == NULL) { check_erb_node_for_missing_end(node); }
|
|
1294
|
+
|
|
1295
|
+
if (if_node->statements != NULL) {
|
|
1296
|
+
for (size_t i = 0; i < hb_array_size(if_node->statements); i++) {
|
|
1297
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(if_node->statements, i);
|
|
1298
|
+
|
|
1299
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
AST_NODE_T* subsequent = if_node->subsequent;
|
|
1304
|
+
|
|
1305
|
+
while (subsequent != NULL) {
|
|
1306
|
+
if (subsequent->type == AST_ERB_CONTENT_NODE) {
|
|
1307
|
+
const AST_ERB_CONTENT_NODE_T* content_node = (const AST_ERB_CONTENT_NODE_T*) subsequent;
|
|
1308
|
+
|
|
1309
|
+
if (content_node->parsed && !content_node->valid && content_node->analyzed_ruby != NULL) {
|
|
1310
|
+
analyzed_ruby_T* analyzed = content_node->analyzed_ruby;
|
|
1311
|
+
const char* keyword = erb_keyword_from_analyzed_ruby(analyzed);
|
|
1312
|
+
|
|
1313
|
+
if (!token_value_empty(content_node->tag_closing)) {
|
|
1314
|
+
append_erb_control_flow_scope_error(
|
|
1315
|
+
keyword,
|
|
1316
|
+
subsequent->location.start,
|
|
1317
|
+
subsequent->location.end,
|
|
1318
|
+
subsequent->errors
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
if (subsequent->type == AST_ERB_IF_NODE) {
|
|
1325
|
+
const AST_ERB_IF_NODE_T* elsif_node = (const AST_ERB_IF_NODE_T*) subsequent;
|
|
1326
|
+
|
|
1327
|
+
if (elsif_node->statements != NULL) {
|
|
1328
|
+
for (size_t i = 0; i < hb_array_size(elsif_node->statements); i++) {
|
|
1329
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(elsif_node->statements, i);
|
|
1330
|
+
|
|
1331
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
subsequent = elsif_node->subsequent;
|
|
1336
|
+
} else if (subsequent->type == AST_ERB_ELSE_NODE) {
|
|
1337
|
+
const AST_ERB_ELSE_NODE_T* else_node = (const AST_ERB_ELSE_NODE_T*) subsequent;
|
|
1338
|
+
|
|
1339
|
+
if (else_node->statements != NULL) {
|
|
1340
|
+
for (size_t i = 0; i < hb_array_size(else_node->statements); i++) {
|
|
1341
|
+
AST_NODE_T* statement = (AST_NODE_T*) hb_array_get(else_node->statements, i);
|
|
1342
|
+
|
|
1343
|
+
if (statement != NULL) { herb_visit_node(statement, detect_invalid_erb_structures, context); }
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
break;
|
|
1348
|
+
} else {
|
|
1349
|
+
break;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1025
1352
|
}
|
|
1026
1353
|
|
|
1027
|
-
if (node->type ==
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
array_free(&old_array);
|
|
1354
|
+
if (node->type == AST_ERB_UNLESS_NODE || node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE
|
|
1355
|
+
|| node->type == AST_ERB_FOR_NODE || node->type == AST_ERB_CASE_NODE || node->type == AST_ERB_CASE_MATCH_NODE
|
|
1356
|
+
|| node->type == AST_ERB_BEGIN_NODE || node->type == AST_ERB_BLOCK_NODE || node->type == AST_ERB_ELSE_NODE) {
|
|
1357
|
+
herb_visit_child_nodes(node, detect_invalid_erb_structures, context);
|
|
1032
1358
|
}
|
|
1033
1359
|
|
|
1034
|
-
if (node->type ==
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1360
|
+
if (node->type == AST_ERB_UNLESS_NODE || node->type == AST_ERB_WHILE_NODE || node->type == AST_ERB_UNTIL_NODE
|
|
1361
|
+
|| node->type == AST_ERB_FOR_NODE || node->type == AST_ERB_CASE_NODE || node->type == AST_ERB_CASE_MATCH_NODE
|
|
1362
|
+
|| node->type == AST_ERB_BEGIN_NODE || node->type == AST_ERB_BLOCK_NODE || node->type == AST_ERB_ELSE_NODE) {
|
|
1363
|
+
check_erb_node_for_missing_end(node);
|
|
1364
|
+
|
|
1365
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1366
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1367
|
+
|
|
1368
|
+
return false;
|
|
1039
1369
|
}
|
|
1040
1370
|
|
|
1041
|
-
if (node->type ==
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1371
|
+
if (node->type == AST_ERB_IF_NODE) {
|
|
1372
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1373
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1374
|
+
|
|
1375
|
+
return false;
|
|
1046
1376
|
}
|
|
1047
1377
|
|
|
1048
|
-
|
|
1378
|
+
bool result = true;
|
|
1049
1379
|
|
|
1050
|
-
|
|
1380
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1381
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1382
|
+
|
|
1383
|
+
return result;
|
|
1051
1384
|
}
|
|
1052
1385
|
|
|
1053
1386
|
void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source) {
|
|
@@ -1056,19 +1389,31 @@ void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source)
|
|
|
1056
1389
|
analyze_ruby_context_T* context = malloc(sizeof(analyze_ruby_context_T));
|
|
1057
1390
|
context->document = document;
|
|
1058
1391
|
context->parent = NULL;
|
|
1059
|
-
context->ruby_context_stack =
|
|
1392
|
+
context->ruby_context_stack = hb_array_init(8);
|
|
1060
1393
|
|
|
1061
1394
|
herb_visit_node((AST_NODE_T*) document, transform_erb_nodes, context);
|
|
1062
1395
|
|
|
1396
|
+
invalid_erb_context_T* invalid_context = malloc(sizeof(invalid_erb_context_T));
|
|
1397
|
+
invalid_context->loop_depth = 0;
|
|
1398
|
+
invalid_context->rescue_depth = 0;
|
|
1399
|
+
|
|
1400
|
+
herb_visit_node((AST_NODE_T*) document, detect_invalid_erb_structures, invalid_context);
|
|
1401
|
+
|
|
1063
1402
|
herb_analyze_parse_errors(document, source);
|
|
1064
1403
|
|
|
1065
|
-
|
|
1404
|
+
herb_parser_match_html_tags_post_analyze(document);
|
|
1405
|
+
|
|
1406
|
+
hb_array_free(&context->ruby_context_stack);
|
|
1407
|
+
|
|
1066
1408
|
free(context);
|
|
1409
|
+
free(invalid_context);
|
|
1067
1410
|
}
|
|
1068
1411
|
|
|
1069
1412
|
void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source) {
|
|
1070
1413
|
char* extracted_ruby = herb_extract_ruby_with_semicolons(source);
|
|
1071
1414
|
|
|
1415
|
+
if (!extracted_ruby) { return; }
|
|
1416
|
+
|
|
1072
1417
|
pm_parser_t parser;
|
|
1073
1418
|
pm_options_t options = { 0, .partial_script = true };
|
|
1074
1419
|
pm_parser_init(&parser, (const uint8_t*) extracted_ruby, strlen(extracted_ruby), &options);
|
|
@@ -1079,7 +1424,7 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source
|
|
|
1079
1424
|
error = (const pm_diagnostic_t*) error->node.next) {
|
|
1080
1425
|
|
|
1081
1426
|
RUBY_PARSE_ERROR_T* parse_error = ruby_parse_error_from_prism_error(error, (AST_NODE_T*) document, source, &parser);
|
|
1082
|
-
|
|
1427
|
+
hb_array_append(document->base.errors, parse_error);
|
|
1083
1428
|
}
|
|
1084
1429
|
|
|
1085
1430
|
pm_node_destroy(&parser, root);
|