herb 0.7.4-x86_64-linux-gnu → 0.8.2-x86_64-linux-gnu
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/README.md +6 -1
- data/config.yml +40 -20
- 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 +12 -18
- data/ext/herb/extension_helpers.h +4 -4
- data/ext/herb/nodes.c +72 -37
- data/herb.gemspec +0 -2
- data/lib/herb/3.0/herb.so +0 -0
- data/lib/herb/3.1/herb.so +0 -0
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +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 +18 -20
- 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 +589 -281
- 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 +14 -17
- data/src/ast_nodes.c +179 -181
- data/src/ast_pretty_print.c +232 -232
- data/src/element_source.c +7 -6
- data/src/errors.c +272 -152
- 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 +4 -4
- data/src/include/ast_nodes.h +68 -67
- data/src/include/ast_pretty_print.h +2 -2
- data/src/include/element_source.h +3 -1
- data/src/include/errors.h +42 -26
- 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 +21 -19
- data/src/include/lexer_struct.h +12 -10
- data/src/include/location.h +10 -13
- data/src/include/macros.h +4 -0
- data/src/include/parser.h +12 -6
- data/src/include/parser_helpers.h +26 -16
- data/src/include/position.h +3 -14
- data/src/include/pretty_print.h +38 -28
- data/src/include/prism_helpers.h +1 -1
- data/src/include/range.h +4 -13
- data/src/include/token.h +5 -11
- data/src/include/token_struct.h +2 -2
- 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 +36 -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 +62 -88
- data/src/lexer_peek_helpers.c +42 -38
- data/src/location.c +9 -37
- data/src/main.c +19 -23
- data/src/parser.c +371 -313
- data/src/parser_helpers.c +60 -54
- data/src/parser_match_tags.c +316 -0
- data/src/pretty_print.c +88 -117
- data/src/prism_helpers.c +7 -7
- data/src/range.c +2 -35
- data/src/token.c +36 -87
- 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 +211 -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/core/src/visitor.ts.erb +29 -1
- 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 -16
- data/templates/src/ast_pretty_print.c.erb +36 -36
- data/templates/src/errors.c.erb +36 -38
- data/templates/src/include/ast_nodes.h.erb +11 -10
- data/templates/src/include/ast_pretty_print.h.erb +2 -2
- data/templates/src/include/errors.h.erb +9 -9
- 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 -21
- 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 -232
- 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/position.c +0 -33
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
|
|
|
@@ -96,31 +229,20 @@ static control_type_t detect_control_type(AST_ERB_CONTENT_NODE_T* erb_node) {
|
|
|
96
229
|
|
|
97
230
|
if (!ruby) { return CONTROL_TYPE_UNKNOWN; }
|
|
98
231
|
|
|
99
|
-
if (ruby->valid) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
232
|
+
if (ruby->valid) { return CONTROL_TYPE_UNKNOWN; }
|
|
233
|
+
|
|
234
|
+
pm_node_t* root = ruby->root;
|
|
103
235
|
|
|
104
|
-
if (has_yield_node(ruby)) { return CONTROL_TYPE_YIELD; }
|
|
105
|
-
if (has_block_node(ruby)) { return CONTROL_TYPE_BLOCK; }
|
|
106
|
-
if (has_if_node(ruby)) { return CONTROL_TYPE_IF; }
|
|
107
236
|
if (has_elsif_node(ruby)) { return CONTROL_TYPE_ELSIF; }
|
|
108
237
|
if (has_else_node(ruby)) { return CONTROL_TYPE_ELSE; }
|
|
109
238
|
if (has_end(ruby)) { return CONTROL_TYPE_END; }
|
|
110
|
-
if (has_case_node(ruby)) { return CONTROL_TYPE_CASE; }
|
|
111
|
-
if (has_case_match_node(ruby)) { return CONTROL_TYPE_CASE_MATCH; }
|
|
112
239
|
if (has_when_node(ruby)) { return CONTROL_TYPE_WHEN; }
|
|
113
240
|
if (has_in_node(ruby)) { return CONTROL_TYPE_IN; }
|
|
114
|
-
if (has_begin_node(ruby)) { return CONTROL_TYPE_BEGIN; }
|
|
115
241
|
if (has_rescue_node(ruby)) { return CONTROL_TYPE_RESCUE; }
|
|
116
242
|
if (has_ensure_node(ruby)) { return CONTROL_TYPE_ENSURE; }
|
|
117
|
-
if (has_unless_node(ruby)) { return CONTROL_TYPE_UNLESS; }
|
|
118
|
-
if (has_while_node(ruby)) { return CONTROL_TYPE_WHILE; }
|
|
119
|
-
if (has_until_node(ruby)) { return CONTROL_TYPE_UNTIL; }
|
|
120
|
-
if (has_for_node(ruby)) { return CONTROL_TYPE_FOR; }
|
|
121
243
|
if (has_block_closing(ruby)) { return CONTROL_TYPE_BLOCK_CLOSE; }
|
|
122
244
|
|
|
123
|
-
return
|
|
245
|
+
return find_earliest_control_keyword(root, ruby->parser.start);
|
|
124
246
|
}
|
|
125
247
|
|
|
126
248
|
static bool is_subsequent_type(control_type_t parent_type, control_type_t child_type) {
|
|
@@ -152,22 +274,24 @@ static bool is_terminator_type(control_type_t parent_type, control_type_t child_
|
|
|
152
274
|
|
|
153
275
|
static AST_NODE_T* create_control_node(
|
|
154
276
|
AST_ERB_CONTENT_NODE_T* erb_node,
|
|
155
|
-
|
|
277
|
+
hb_array_T* children,
|
|
156
278
|
AST_NODE_T* subsequent,
|
|
157
279
|
AST_ERB_END_NODE_T* end_node,
|
|
158
280
|
control_type_t control_type
|
|
159
281
|
) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
282
|
+
hb_array_T* errors = erb_node->base.errors;
|
|
283
|
+
erb_node->base.errors = NULL;
|
|
284
|
+
|
|
285
|
+
position_T start_position = erb_node->tag_opening->location.start;
|
|
286
|
+
position_T end_position = erb_node->tag_closing->location.end;
|
|
163
287
|
|
|
164
288
|
if (end_node) {
|
|
165
|
-
end_position = end_node->base.location
|
|
166
|
-
} else if (children &&
|
|
167
|
-
AST_NODE_T* last_child =
|
|
168
|
-
end_position = last_child->location
|
|
289
|
+
end_position = end_node->base.location.end;
|
|
290
|
+
} else if (children && hb_array_size(children) > 0) {
|
|
291
|
+
AST_NODE_T* last_child = hb_array_last(children);
|
|
292
|
+
end_position = last_child->location.end;
|
|
169
293
|
} else if (subsequent) {
|
|
170
|
-
end_position = subsequent->location
|
|
294
|
+
end_position = subsequent->location.end;
|
|
171
295
|
}
|
|
172
296
|
|
|
173
297
|
token_T* tag_opening = erb_node->tag_opening;
|
|
@@ -176,7 +300,7 @@ static AST_NODE_T* create_control_node(
|
|
|
176
300
|
|
|
177
301
|
switch (control_type) {
|
|
178
302
|
case CONTROL_TYPE_IF:
|
|
179
|
-
case CONTROL_TYPE_ELSIF:
|
|
303
|
+
case CONTROL_TYPE_ELSIF: {
|
|
180
304
|
return (AST_NODE_T*) ast_erb_if_node_init(
|
|
181
305
|
tag_opening,
|
|
182
306
|
content,
|
|
@@ -188,32 +312,40 @@ static AST_NODE_T* create_control_node(
|
|
|
188
312
|
end_position,
|
|
189
313
|
errors
|
|
190
314
|
);
|
|
315
|
+
}
|
|
191
316
|
|
|
192
|
-
case CONTROL_TYPE_ELSE:
|
|
193
|
-
return (
|
|
194
|
-
|
|
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
|
+
}
|
|
195
322
|
|
|
196
323
|
case CONTROL_TYPE_CASE:
|
|
197
324
|
case CONTROL_TYPE_CASE_MATCH: {
|
|
198
325
|
AST_ERB_ELSE_NODE_T* else_node = NULL;
|
|
199
326
|
if (subsequent && subsequent->type == AST_ERB_ELSE_NODE) { else_node = (AST_ERB_ELSE_NODE_T*) subsequent; }
|
|
200
327
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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);
|
|
204
334
|
|
|
205
|
-
for (size_t i = 0; i < array_size(children); i++) {
|
|
206
|
-
AST_NODE_T* child = array_get(children, i);
|
|
207
335
|
if (child && child->type == AST_ERB_WHEN_NODE) {
|
|
208
|
-
|
|
336
|
+
hb_array_append(when_conditions, child);
|
|
209
337
|
} else if (child && child->type == AST_ERB_IN_NODE) {
|
|
210
|
-
|
|
338
|
+
hb_array_append(in_conditions, child);
|
|
211
339
|
} else {
|
|
212
|
-
|
|
340
|
+
hb_array_append(non_when_non_in_children, child);
|
|
213
341
|
}
|
|
214
342
|
}
|
|
215
343
|
|
|
216
|
-
|
|
344
|
+
hb_array_free(&children);
|
|
345
|
+
|
|
346
|
+
if (hb_array_size(in_conditions) > 0) {
|
|
347
|
+
hb_array_free(&when_conditions);
|
|
348
|
+
|
|
217
349
|
return (AST_NODE_T*) ast_erb_case_match_node_init(
|
|
218
350
|
tag_opening,
|
|
219
351
|
content,
|
|
@@ -226,30 +358,34 @@ static AST_NODE_T* create_control_node(
|
|
|
226
358
|
end_position,
|
|
227
359
|
errors
|
|
228
360
|
);
|
|
229
|
-
}
|
|
361
|
+
} else {
|
|
362
|
+
hb_array_free(&in_conditions);
|
|
230
363
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
+
}
|
|
243
377
|
}
|
|
244
378
|
|
|
245
379
|
case CONTROL_TYPE_WHEN: {
|
|
246
|
-
return (
|
|
247
|
-
|
|
380
|
+
return (
|
|
381
|
+
AST_NODE_T*
|
|
382
|
+
) ast_erb_when_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
248
383
|
}
|
|
249
384
|
|
|
250
385
|
case CONTROL_TYPE_IN: {
|
|
251
|
-
return (
|
|
252
|
-
|
|
386
|
+
return (
|
|
387
|
+
AST_NODE_T*
|
|
388
|
+
) ast_erb_in_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
253
389
|
}
|
|
254
390
|
|
|
255
391
|
case CONTROL_TYPE_BEGIN: {
|
|
@@ -300,8 +436,9 @@ static AST_NODE_T* create_control_node(
|
|
|
300
436
|
}
|
|
301
437
|
|
|
302
438
|
case CONTROL_TYPE_ENSURE: {
|
|
303
|
-
return (
|
|
304
|
-
|
|
439
|
+
return (
|
|
440
|
+
AST_NODE_T*
|
|
441
|
+
) ast_erb_ensure_node_init(tag_opening, content, tag_closing, children, start_position, end_position, errors);
|
|
305
442
|
}
|
|
306
443
|
|
|
307
444
|
case CONTROL_TYPE_UNLESS: {
|
|
@@ -375,34 +512,35 @@ static AST_NODE_T* create_control_node(
|
|
|
375
512
|
}
|
|
376
513
|
|
|
377
514
|
case CONTROL_TYPE_YIELD: {
|
|
378
|
-
return (
|
|
379
|
-
|
|
515
|
+
return (
|
|
516
|
+
AST_NODE_T*
|
|
517
|
+
) ast_erb_yield_node_init(tag_opening, content, tag_closing, start_position, end_position, errors);
|
|
380
518
|
}
|
|
381
519
|
|
|
382
|
-
default:
|
|
520
|
+
default: return NULL;
|
|
383
521
|
}
|
|
384
522
|
}
|
|
385
523
|
|
|
386
524
|
static size_t process_control_structure(
|
|
387
525
|
AST_NODE_T* node,
|
|
388
|
-
|
|
526
|
+
hb_array_T* array,
|
|
389
527
|
size_t index,
|
|
390
|
-
|
|
528
|
+
hb_array_T* output_array,
|
|
391
529
|
analyze_ruby_context_T* context,
|
|
392
530
|
control_type_t initial_type
|
|
393
531
|
) {
|
|
394
|
-
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*)
|
|
395
|
-
|
|
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);
|
|
396
534
|
|
|
397
535
|
index++;
|
|
398
536
|
|
|
399
537
|
if (initial_type == CONTROL_TYPE_CASE || initial_type == CONTROL_TYPE_CASE_MATCH) {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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);
|
|
403
541
|
|
|
404
|
-
while (index <
|
|
405
|
-
AST_NODE_T* next_node =
|
|
542
|
+
while (index < hb_array_size(array)) {
|
|
543
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
406
544
|
|
|
407
545
|
if (!next_node) { break; }
|
|
408
546
|
|
|
@@ -413,17 +551,17 @@ static size_t process_control_structure(
|
|
|
413
551
|
if (next_type == CONTROL_TYPE_WHEN || next_type == CONTROL_TYPE_IN) { break; }
|
|
414
552
|
}
|
|
415
553
|
|
|
416
|
-
|
|
554
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
417
555
|
index++;
|
|
418
556
|
}
|
|
419
557
|
|
|
420
|
-
while (index <
|
|
421
|
-
AST_NODE_T* next_node =
|
|
558
|
+
while (index < hb_array_size(array)) {
|
|
559
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
422
560
|
|
|
423
561
|
if (!next_node) { break; }
|
|
424
562
|
|
|
425
563
|
if (next_node->type != AST_ERB_CONTENT_NODE) {
|
|
426
|
-
|
|
564
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
427
565
|
index++;
|
|
428
566
|
continue;
|
|
429
567
|
}
|
|
@@ -432,167 +570,142 @@ static size_t process_control_structure(
|
|
|
432
570
|
control_type_t next_type = detect_control_type(erb_content);
|
|
433
571
|
|
|
434
572
|
if (next_type == CONTROL_TYPE_WHEN) {
|
|
435
|
-
|
|
573
|
+
hb_array_T* when_statements = hb_array_init(8);
|
|
436
574
|
index++;
|
|
437
575
|
|
|
438
|
-
|
|
439
|
-
AST_NODE_T* child = array_get(array, index);
|
|
440
|
-
|
|
441
|
-
if (!child) { break; }
|
|
442
|
-
|
|
443
|
-
if (child->type == AST_ERB_CONTENT_NODE) {
|
|
444
|
-
AST_ERB_CONTENT_NODE_T* child_erb = (AST_ERB_CONTENT_NODE_T*) child;
|
|
445
|
-
control_type_t child_type = detect_control_type(child_erb);
|
|
576
|
+
index = process_block_children(node, array, index, when_statements, context, CONTROL_TYPE_WHEN);
|
|
446
577
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
break;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
array_append(when_statements, child);
|
|
454
|
-
index++;
|
|
455
|
-
}
|
|
578
|
+
hb_array_T* when_errors = erb_content->base.errors;
|
|
579
|
+
erb_content->base.errors = NULL;
|
|
456
580
|
|
|
457
581
|
AST_ERB_WHEN_NODE_T* when_node = ast_erb_when_node_init(
|
|
458
582
|
erb_content->tag_opening,
|
|
459
583
|
erb_content->content,
|
|
460
584
|
erb_content->tag_closing,
|
|
461
585
|
when_statements,
|
|
462
|
-
erb_content->tag_opening->location
|
|
463
|
-
erb_content->tag_closing->location
|
|
464
|
-
|
|
586
|
+
erb_content->tag_opening->location.start,
|
|
587
|
+
erb_content->tag_closing->location.end,
|
|
588
|
+
when_errors
|
|
465
589
|
);
|
|
466
590
|
|
|
467
|
-
|
|
591
|
+
ast_node_free((AST_NODE_T*) erb_content);
|
|
592
|
+
|
|
593
|
+
hb_array_append(when_conditions, (AST_NODE_T*) when_node);
|
|
468
594
|
|
|
469
595
|
continue;
|
|
470
596
|
} else if (next_type == CONTROL_TYPE_IN) {
|
|
471
|
-
|
|
597
|
+
hb_array_T* in_statements = hb_array_init(8);
|
|
472
598
|
index++;
|
|
473
599
|
|
|
474
|
-
|
|
475
|
-
AST_NODE_T* child = array_get(array, index);
|
|
476
|
-
|
|
477
|
-
if (!child) { break; }
|
|
600
|
+
index = process_block_children(node, array, index, in_statements, context, CONTROL_TYPE_IN);
|
|
478
601
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
control_type_t child_type = detect_control_type(child_erb);
|
|
482
|
-
|
|
483
|
-
if (child_type == CONTROL_TYPE_IN || child_type == CONTROL_TYPE_WHEN || child_type == CONTROL_TYPE_ELSE
|
|
484
|
-
|| child_type == CONTROL_TYPE_END) {
|
|
485
|
-
break;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
array_append(in_statements, child);
|
|
490
|
-
index++;
|
|
491
|
-
}
|
|
602
|
+
hb_array_T* in_errors = erb_content->base.errors;
|
|
603
|
+
erb_content->base.errors = NULL;
|
|
492
604
|
|
|
493
605
|
AST_ERB_IN_NODE_T* in_node = ast_erb_in_node_init(
|
|
494
606
|
erb_content->tag_opening,
|
|
495
607
|
erb_content->content,
|
|
496
608
|
erb_content->tag_closing,
|
|
497
609
|
in_statements,
|
|
498
|
-
erb_content->tag_opening->location
|
|
499
|
-
erb_content->tag_closing->location
|
|
500
|
-
|
|
610
|
+
erb_content->tag_opening->location.start,
|
|
611
|
+
erb_content->tag_closing->location.end,
|
|
612
|
+
in_errors
|
|
501
613
|
);
|
|
502
614
|
|
|
503
|
-
|
|
615
|
+
ast_node_free((AST_NODE_T*) erb_content);
|
|
616
|
+
|
|
617
|
+
hb_array_append(in_conditions, (AST_NODE_T*) in_node);
|
|
504
618
|
|
|
505
619
|
continue;
|
|
506
620
|
} else if (next_type == CONTROL_TYPE_ELSE || next_type == CONTROL_TYPE_END) {
|
|
507
621
|
break;
|
|
508
622
|
} else {
|
|
509
|
-
|
|
623
|
+
hb_array_append(non_when_non_in_children, next_node);
|
|
510
624
|
index++;
|
|
511
625
|
}
|
|
512
626
|
}
|
|
513
627
|
|
|
514
628
|
AST_ERB_ELSE_NODE_T* else_clause = NULL;
|
|
515
629
|
|
|
516
|
-
if (index <
|
|
517
|
-
AST_NODE_T* next_node =
|
|
630
|
+
if (index < hb_array_size(array)) {
|
|
631
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
518
632
|
|
|
519
633
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
520
634
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
521
635
|
control_type_t next_type = detect_control_type(next_erb);
|
|
522
636
|
|
|
523
637
|
if (next_type == CONTROL_TYPE_ELSE) {
|
|
524
|
-
|
|
638
|
+
hb_array_T* else_children = hb_array_init(8);
|
|
525
639
|
|
|
526
640
|
index++;
|
|
527
641
|
|
|
528
|
-
|
|
529
|
-
AST_NODE_T* child = array_get(array, index);
|
|
642
|
+
index = process_block_children(node, array, index, else_children, context, initial_type);
|
|
530
643
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
if (child->type == AST_ERB_CONTENT_NODE) {
|
|
534
|
-
AST_ERB_CONTENT_NODE_T* child_erb = (AST_ERB_CONTENT_NODE_T*) child;
|
|
535
|
-
control_type_t child_type = detect_control_type(child_erb);
|
|
536
|
-
|
|
537
|
-
if (child_type == CONTROL_TYPE_END) { break; }
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
array_append(else_children, child);
|
|
541
|
-
index++;
|
|
542
|
-
}
|
|
644
|
+
hb_array_T* else_errors = next_erb->base.errors;
|
|
645
|
+
next_erb->base.errors = NULL;
|
|
543
646
|
|
|
544
647
|
else_clause = ast_erb_else_node_init(
|
|
545
648
|
next_erb->tag_opening,
|
|
546
649
|
next_erb->content,
|
|
547
650
|
next_erb->tag_closing,
|
|
548
651
|
else_children,
|
|
549
|
-
next_erb->tag_opening->location
|
|
550
|
-
next_erb->tag_closing->location
|
|
551
|
-
|
|
652
|
+
next_erb->tag_opening->location.start,
|
|
653
|
+
next_erb->tag_closing->location.end,
|
|
654
|
+
else_errors
|
|
552
655
|
);
|
|
656
|
+
|
|
657
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
553
658
|
}
|
|
554
659
|
}
|
|
555
660
|
}
|
|
556
661
|
|
|
557
662
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
558
663
|
|
|
559
|
-
if (index <
|
|
560
|
-
AST_NODE_T* potential_end =
|
|
664
|
+
if (index < hb_array_size(array)) {
|
|
665
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
561
666
|
|
|
562
667
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
563
668
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
564
669
|
|
|
565
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
|
+
|
|
566
674
|
end_node = ast_erb_end_node_init(
|
|
567
675
|
end_erb->tag_opening,
|
|
568
676
|
end_erb->content,
|
|
569
677
|
end_erb->tag_closing,
|
|
570
|
-
end_erb->tag_opening->location
|
|
571
|
-
end_erb->tag_closing->location
|
|
572
|
-
|
|
678
|
+
end_erb->tag_opening->location.start,
|
|
679
|
+
end_erb->tag_closing->location.end,
|
|
680
|
+
end_errors
|
|
573
681
|
);
|
|
574
682
|
|
|
683
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
684
|
+
|
|
575
685
|
index++;
|
|
576
686
|
}
|
|
577
687
|
}
|
|
578
688
|
}
|
|
579
689
|
|
|
580
|
-
position_T
|
|
581
|
-
position_T
|
|
690
|
+
position_T start_position = erb_node->tag_opening->location.start;
|
|
691
|
+
position_T end_position = erb_node->tag_closing->location.end;
|
|
582
692
|
|
|
583
693
|
if (end_node) {
|
|
584
|
-
end_position = end_node->base.location
|
|
694
|
+
end_position = end_node->base.location.end;
|
|
585
695
|
} else if (else_clause) {
|
|
586
|
-
end_position = else_clause->base.location
|
|
587
|
-
} else if (
|
|
588
|
-
AST_NODE_T* last_when =
|
|
589
|
-
end_position = last_when->location
|
|
590
|
-
} else if (
|
|
591
|
-
AST_NODE_T* last_in =
|
|
592
|
-
end_position = last_in->location
|
|
696
|
+
end_position = else_clause->base.location.end;
|
|
697
|
+
} else if (hb_array_size(when_conditions) > 0) {
|
|
698
|
+
AST_NODE_T* last_when = hb_array_last(when_conditions);
|
|
699
|
+
end_position = last_when->location.end;
|
|
700
|
+
} else if (hb_array_size(in_conditions) > 0) {
|
|
701
|
+
AST_NODE_T* last_in = hb_array_last(in_conditions);
|
|
702
|
+
end_position = last_in->location.end;
|
|
593
703
|
}
|
|
594
704
|
|
|
595
|
-
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
|
+
|
|
596
709
|
AST_ERB_CASE_MATCH_NODE_T* case_match_node = ast_erb_case_match_node_init(
|
|
597
710
|
erb_node->tag_opening,
|
|
598
711
|
erb_node->content,
|
|
@@ -603,13 +716,21 @@ static size_t process_control_structure(
|
|
|
603
716
|
end_node,
|
|
604
717
|
start_position,
|
|
605
718
|
end_position,
|
|
606
|
-
|
|
719
|
+
case_match_errors
|
|
607
720
|
);
|
|
608
721
|
|
|
609
|
-
|
|
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
|
+
|
|
610
728
|
return index;
|
|
611
729
|
}
|
|
612
730
|
|
|
731
|
+
hb_array_T* case_errors = erb_node->base.errors;
|
|
732
|
+
erb_node->base.errors = NULL;
|
|
733
|
+
|
|
613
734
|
AST_ERB_CASE_NODE_T* case_node = ast_erb_case_node_init(
|
|
614
735
|
erb_node->tag_opening,
|
|
615
736
|
erb_node->content,
|
|
@@ -620,10 +741,15 @@ static size_t process_control_structure(
|
|
|
620
741
|
end_node,
|
|
621
742
|
start_position,
|
|
622
743
|
end_position,
|
|
623
|
-
|
|
744
|
+
case_errors
|
|
624
745
|
);
|
|
625
746
|
|
|
626
|
-
|
|
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
|
+
|
|
627
753
|
return index;
|
|
628
754
|
}
|
|
629
755
|
|
|
@@ -634,8 +760,8 @@ static size_t process_control_structure(
|
|
|
634
760
|
AST_ERB_ELSE_NODE_T* else_clause = NULL;
|
|
635
761
|
AST_ERB_ENSURE_NODE_T* ensure_clause = NULL;
|
|
636
762
|
|
|
637
|
-
if (index <
|
|
638
|
-
AST_NODE_T* next_node =
|
|
763
|
+
if (index < hb_array_size(array)) {
|
|
764
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
639
765
|
|
|
640
766
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
641
767
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -649,61 +775,52 @@ static size_t process_control_structure(
|
|
|
649
775
|
}
|
|
650
776
|
}
|
|
651
777
|
|
|
652
|
-
if (index <
|
|
653
|
-
AST_NODE_T* next_node =
|
|
778
|
+
if (index < hb_array_size(array)) {
|
|
779
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
654
780
|
|
|
655
781
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
656
782
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
657
783
|
control_type_t next_type = detect_control_type(next_erb);
|
|
658
784
|
|
|
659
785
|
if (next_type == CONTROL_TYPE_ELSE) {
|
|
660
|
-
|
|
786
|
+
hb_array_T* else_children = hb_array_init(8);
|
|
661
787
|
|
|
662
788
|
index++;
|
|
663
789
|
|
|
664
|
-
|
|
665
|
-
AST_NODE_T* child = array_get(array, index);
|
|
666
|
-
|
|
667
|
-
if (!child) { break; }
|
|
668
|
-
|
|
669
|
-
if (child->type == AST_ERB_CONTENT_NODE) {
|
|
670
|
-
AST_ERB_CONTENT_NODE_T* child_erb = (AST_ERB_CONTENT_NODE_T*) child;
|
|
671
|
-
control_type_t child_type = detect_control_type(child_erb);
|
|
672
|
-
|
|
673
|
-
if (child_type == CONTROL_TYPE_ENSURE || child_type == CONTROL_TYPE_END) { break; }
|
|
674
|
-
}
|
|
790
|
+
index = process_block_children(node, array, index, else_children, context, initial_type);
|
|
675
791
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
}
|
|
792
|
+
hb_array_T* else_errors = next_erb->base.errors;
|
|
793
|
+
next_erb->base.errors = NULL;
|
|
679
794
|
|
|
680
795
|
else_clause = ast_erb_else_node_init(
|
|
681
796
|
next_erb->tag_opening,
|
|
682
797
|
next_erb->content,
|
|
683
798
|
next_erb->tag_closing,
|
|
684
799
|
else_children,
|
|
685
|
-
next_erb->tag_opening->location
|
|
686
|
-
next_erb->tag_closing->location
|
|
687
|
-
|
|
800
|
+
next_erb->tag_opening->location.start,
|
|
801
|
+
next_erb->tag_closing->location.end,
|
|
802
|
+
else_errors
|
|
688
803
|
);
|
|
804
|
+
|
|
805
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
689
806
|
}
|
|
690
807
|
}
|
|
691
808
|
}
|
|
692
809
|
|
|
693
|
-
if (index <
|
|
694
|
-
AST_NODE_T* next_node =
|
|
810
|
+
if (index < hb_array_size(array)) {
|
|
811
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
695
812
|
|
|
696
813
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
697
814
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
698
815
|
control_type_t next_type = detect_control_type(next_erb);
|
|
699
816
|
|
|
700
817
|
if (next_type == CONTROL_TYPE_ENSURE) {
|
|
701
|
-
|
|
818
|
+
hb_array_T* ensure_children = hb_array_init(8);
|
|
702
819
|
|
|
703
820
|
index++;
|
|
704
821
|
|
|
705
|
-
while (index <
|
|
706
|
-
AST_NODE_T* child =
|
|
822
|
+
while (index < hb_array_size(array)) {
|
|
823
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
707
824
|
|
|
708
825
|
if (!child) { break; }
|
|
709
826
|
|
|
@@ -714,59 +831,72 @@ static size_t process_control_structure(
|
|
|
714
831
|
if (child_type == CONTROL_TYPE_END) { break; }
|
|
715
832
|
}
|
|
716
833
|
|
|
717
|
-
|
|
834
|
+
hb_array_append(ensure_children, child);
|
|
718
835
|
index++;
|
|
719
836
|
}
|
|
720
837
|
|
|
838
|
+
hb_array_T* ensure_errors = next_erb->base.errors;
|
|
839
|
+
next_erb->base.errors = NULL;
|
|
840
|
+
|
|
721
841
|
ensure_clause = ast_erb_ensure_node_init(
|
|
722
842
|
next_erb->tag_opening,
|
|
723
843
|
next_erb->content,
|
|
724
844
|
next_erb->tag_closing,
|
|
725
845
|
ensure_children,
|
|
726
|
-
next_erb->tag_opening->location
|
|
727
|
-
next_erb->tag_closing->location
|
|
728
|
-
|
|
846
|
+
next_erb->tag_opening->location.start,
|
|
847
|
+
next_erb->tag_closing->location.end,
|
|
848
|
+
ensure_errors
|
|
729
849
|
);
|
|
850
|
+
|
|
851
|
+
ast_node_free((AST_NODE_T*) next_erb);
|
|
730
852
|
}
|
|
731
853
|
}
|
|
732
854
|
}
|
|
733
855
|
|
|
734
856
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
735
857
|
|
|
736
|
-
if (index <
|
|
737
|
-
AST_NODE_T* potential_end =
|
|
858
|
+
if (index < hb_array_size(array)) {
|
|
859
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
738
860
|
|
|
739
861
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
740
862
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
741
863
|
|
|
742
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
|
+
|
|
743
868
|
end_node = ast_erb_end_node_init(
|
|
744
869
|
end_erb->tag_opening,
|
|
745
870
|
end_erb->content,
|
|
746
871
|
end_erb->tag_closing,
|
|
747
|
-
end_erb->tag_opening->location
|
|
748
|
-
end_erb->tag_closing->location
|
|
749
|
-
|
|
872
|
+
end_erb->tag_opening->location.start,
|
|
873
|
+
end_erb->tag_closing->location.end,
|
|
874
|
+
end_errors
|
|
750
875
|
);
|
|
751
876
|
|
|
877
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
878
|
+
|
|
752
879
|
index++;
|
|
753
880
|
}
|
|
754
881
|
}
|
|
755
882
|
}
|
|
756
883
|
|
|
757
|
-
position_T
|
|
758
|
-
position_T
|
|
884
|
+
position_T start_position = erb_node->tag_opening->location.start;
|
|
885
|
+
position_T end_position = erb_node->tag_closing->location.end;
|
|
759
886
|
|
|
760
887
|
if (end_node) {
|
|
761
|
-
end_position = end_node->base.location
|
|
888
|
+
end_position = end_node->base.location.end;
|
|
762
889
|
} else if (ensure_clause) {
|
|
763
|
-
end_position = ensure_clause->base.location
|
|
890
|
+
end_position = ensure_clause->base.location.end;
|
|
764
891
|
} else if (else_clause) {
|
|
765
|
-
end_position = else_clause->base.location
|
|
892
|
+
end_position = else_clause->base.location.end;
|
|
766
893
|
} else if (rescue_clause) {
|
|
767
|
-
end_position = rescue_clause->base.location
|
|
894
|
+
end_position = rescue_clause->base.location.end;
|
|
768
895
|
}
|
|
769
896
|
|
|
897
|
+
hb_array_T* begin_errors = erb_node->base.errors;
|
|
898
|
+
erb_node->base.errors = NULL;
|
|
899
|
+
|
|
770
900
|
AST_ERB_BEGIN_NODE_T* begin_node = ast_erb_begin_node_init(
|
|
771
901
|
erb_node->tag_opening,
|
|
772
902
|
erb_node->content,
|
|
@@ -778,10 +908,12 @@ static size_t process_control_structure(
|
|
|
778
908
|
end_node,
|
|
779
909
|
start_position,
|
|
780
910
|
end_position,
|
|
781
|
-
|
|
911
|
+
begin_errors
|
|
782
912
|
);
|
|
783
913
|
|
|
784
|
-
|
|
914
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
915
|
+
|
|
916
|
+
hb_array_append(output_array, (AST_NODE_T*) begin_node);
|
|
785
917
|
return index;
|
|
786
918
|
}
|
|
787
919
|
|
|
@@ -790,38 +922,46 @@ static size_t process_control_structure(
|
|
|
790
922
|
|
|
791
923
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
792
924
|
|
|
793
|
-
if (index <
|
|
794
|
-
AST_NODE_T* potential_close =
|
|
925
|
+
if (index < hb_array_size(array)) {
|
|
926
|
+
AST_NODE_T* potential_close = hb_array_get(array, index);
|
|
795
927
|
|
|
796
928
|
if (potential_close && potential_close->type == AST_ERB_CONTENT_NODE) {
|
|
797
929
|
AST_ERB_CONTENT_NODE_T* close_erb = (AST_ERB_CONTENT_NODE_T*) potential_close;
|
|
798
930
|
control_type_t close_type = detect_control_type(close_erb);
|
|
799
931
|
|
|
800
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
|
+
|
|
801
936
|
end_node = ast_erb_end_node_init(
|
|
802
937
|
close_erb->tag_opening,
|
|
803
938
|
close_erb->content,
|
|
804
939
|
close_erb->tag_closing,
|
|
805
|
-
close_erb->tag_opening->location
|
|
806
|
-
close_erb->tag_closing->location
|
|
807
|
-
|
|
940
|
+
close_erb->tag_opening->location.start,
|
|
941
|
+
close_erb->tag_closing->location.end,
|
|
942
|
+
end_errors
|
|
808
943
|
);
|
|
809
944
|
|
|
945
|
+
ast_node_free((AST_NODE_T*) close_erb);
|
|
946
|
+
|
|
810
947
|
index++;
|
|
811
948
|
}
|
|
812
949
|
}
|
|
813
950
|
}
|
|
814
951
|
|
|
815
|
-
position_T
|
|
816
|
-
position_T
|
|
952
|
+
position_T start_position = erb_node->tag_opening->location.start;
|
|
953
|
+
position_T end_position = erb_node->tag_closing->location.end;
|
|
817
954
|
|
|
818
955
|
if (end_node) {
|
|
819
|
-
end_position = end_node->base.location
|
|
820
|
-
} else if (children &&
|
|
821
|
-
AST_NODE_T* last_child =
|
|
822
|
-
end_position = last_child->location
|
|
956
|
+
end_position = end_node->base.location.end;
|
|
957
|
+
} else if (children && hb_array_size(children) > 0) {
|
|
958
|
+
AST_NODE_T* last_child = hb_array_last(children);
|
|
959
|
+
end_position = last_child->location.end;
|
|
823
960
|
}
|
|
824
961
|
|
|
962
|
+
hb_array_T* block_errors = erb_node->base.errors;
|
|
963
|
+
erb_node->base.errors = NULL;
|
|
964
|
+
|
|
825
965
|
AST_ERB_BLOCK_NODE_T* block_node = ast_erb_block_node_init(
|
|
826
966
|
erb_node->tag_opening,
|
|
827
967
|
erb_node->content,
|
|
@@ -830,10 +970,12 @@ static size_t process_control_structure(
|
|
|
830
970
|
end_node,
|
|
831
971
|
start_position,
|
|
832
972
|
end_position,
|
|
833
|
-
|
|
973
|
+
block_errors
|
|
834
974
|
);
|
|
835
975
|
|
|
836
|
-
|
|
976
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
977
|
+
|
|
978
|
+
hb_array_append(output_array, (AST_NODE_T*) block_node);
|
|
837
979
|
return index;
|
|
838
980
|
}
|
|
839
981
|
|
|
@@ -842,8 +984,8 @@ static size_t process_control_structure(
|
|
|
842
984
|
AST_NODE_T* subsequent = NULL;
|
|
843
985
|
AST_ERB_END_NODE_T* end_node = NULL;
|
|
844
986
|
|
|
845
|
-
if (index <
|
|
846
|
-
AST_NODE_T* next_node =
|
|
987
|
+
if (index < hb_array_size(array)) {
|
|
988
|
+
AST_NODE_T* next_node = hb_array_get(array, index);
|
|
847
989
|
|
|
848
990
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
849
991
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -855,22 +997,27 @@ static size_t process_control_structure(
|
|
|
855
997
|
}
|
|
856
998
|
}
|
|
857
999
|
|
|
858
|
-
if (index <
|
|
859
|
-
AST_NODE_T* potential_end =
|
|
1000
|
+
if (index < hb_array_size(array)) {
|
|
1001
|
+
AST_NODE_T* potential_end = hb_array_get(array, index);
|
|
860
1002
|
|
|
861
1003
|
if (potential_end && potential_end->type == AST_ERB_CONTENT_NODE) {
|
|
862
1004
|
AST_ERB_CONTENT_NODE_T* end_erb = (AST_ERB_CONTENT_NODE_T*) potential_end;
|
|
863
1005
|
|
|
864
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
|
+
|
|
865
1010
|
end_node = ast_erb_end_node_init(
|
|
866
1011
|
end_erb->tag_opening,
|
|
867
1012
|
end_erb->content,
|
|
868
1013
|
end_erb->tag_closing,
|
|
869
|
-
end_erb->tag_opening->location
|
|
870
|
-
end_erb->tag_closing->location
|
|
871
|
-
|
|
1014
|
+
end_erb->tag_opening->location.start,
|
|
1015
|
+
end_erb->tag_closing->location.end,
|
|
1016
|
+
end_errors
|
|
872
1017
|
);
|
|
873
1018
|
|
|
1019
|
+
ast_node_free((AST_NODE_T*) end_erb);
|
|
1020
|
+
|
|
874
1021
|
index++;
|
|
875
1022
|
}
|
|
876
1023
|
}
|
|
@@ -878,22 +1025,27 @@ static size_t process_control_structure(
|
|
|
878
1025
|
|
|
879
1026
|
AST_NODE_T* control_node = create_control_node(erb_node, children, subsequent, end_node, initial_type);
|
|
880
1027
|
|
|
881
|
-
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
|
+
}
|
|
882
1034
|
|
|
883
1035
|
return index;
|
|
884
1036
|
}
|
|
885
1037
|
|
|
886
1038
|
static size_t process_subsequent_block(
|
|
887
1039
|
AST_NODE_T* node,
|
|
888
|
-
|
|
1040
|
+
hb_array_T* array,
|
|
889
1041
|
size_t index,
|
|
890
1042
|
AST_NODE_T** subsequent_out,
|
|
891
1043
|
analyze_ruby_context_T* context,
|
|
892
1044
|
control_type_t parent_type
|
|
893
1045
|
) {
|
|
894
|
-
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);
|
|
895
1047
|
control_type_t type = detect_control_type(erb_node);
|
|
896
|
-
|
|
1048
|
+
hb_array_T* children = hb_array_init(8);
|
|
897
1049
|
|
|
898
1050
|
index++;
|
|
899
1051
|
|
|
@@ -901,8 +1053,14 @@ static size_t process_subsequent_block(
|
|
|
901
1053
|
|
|
902
1054
|
AST_NODE_T* subsequent_node = create_control_node(erb_node, children, NULL, NULL, type);
|
|
903
1055
|
|
|
904
|
-
if (
|
|
905
|
-
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);
|
|
906
1064
|
|
|
907
1065
|
if (next_node && next_node->type == AST_ERB_CONTENT_NODE) {
|
|
908
1066
|
AST_ERB_CONTENT_NODE_T* next_erb = (AST_ERB_CONTENT_NODE_T*) next_node;
|
|
@@ -953,19 +1111,19 @@ static size_t process_subsequent_block(
|
|
|
953
1111
|
|
|
954
1112
|
static size_t process_block_children(
|
|
955
1113
|
AST_NODE_T* node,
|
|
956
|
-
|
|
1114
|
+
hb_array_T* array,
|
|
957
1115
|
size_t index,
|
|
958
|
-
|
|
1116
|
+
hb_array_T* children_array,
|
|
959
1117
|
analyze_ruby_context_T* context,
|
|
960
1118
|
control_type_t parent_type
|
|
961
1119
|
) {
|
|
962
|
-
while (index <
|
|
963
|
-
AST_NODE_T* child =
|
|
1120
|
+
while (index < hb_array_size(array)) {
|
|
1121
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
964
1122
|
|
|
965
1123
|
if (!child) { break; }
|
|
966
1124
|
|
|
967
1125
|
if (child->type != AST_ERB_CONTENT_NODE) {
|
|
968
|
-
|
|
1126
|
+
hb_array_append(children_array, child);
|
|
969
1127
|
index++;
|
|
970
1128
|
continue;
|
|
971
1129
|
}
|
|
@@ -978,35 +1136,35 @@ static size_t process_block_children(
|
|
|
978
1136
|
if (child_type == CONTROL_TYPE_IF || child_type == CONTROL_TYPE_CASE || child_type == CONTROL_TYPE_CASE_MATCH
|
|
979
1137
|
|| child_type == CONTROL_TYPE_BEGIN || child_type == CONTROL_TYPE_UNLESS || child_type == CONTROL_TYPE_WHILE
|
|
980
1138
|
|| child_type == CONTROL_TYPE_UNTIL || child_type == CONTROL_TYPE_FOR || child_type == CONTROL_TYPE_BLOCK) {
|
|
981
|
-
|
|
1139
|
+
hb_array_T* temp_array = hb_array_init(1);
|
|
982
1140
|
size_t new_index = process_control_structure(node, array, index, temp_array, context, child_type);
|
|
983
1141
|
|
|
984
|
-
if (
|
|
1142
|
+
if (hb_array_size(temp_array) > 0) { hb_array_append(children_array, hb_array_first(temp_array)); }
|
|
985
1143
|
|
|
986
|
-
|
|
1144
|
+
hb_array_free(&temp_array);
|
|
987
1145
|
|
|
988
1146
|
index = new_index;
|
|
989
1147
|
continue;
|
|
990
1148
|
}
|
|
991
1149
|
|
|
992
|
-
|
|
1150
|
+
hb_array_append(children_array, child);
|
|
993
1151
|
index++;
|
|
994
1152
|
}
|
|
995
1153
|
|
|
996
1154
|
return index;
|
|
997
1155
|
}
|
|
998
1156
|
|
|
999
|
-
|
|
1000
|
-
|
|
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));
|
|
1001
1159
|
size_t index = 0;
|
|
1002
1160
|
|
|
1003
|
-
while (index <
|
|
1004
|
-
AST_NODE_T* item =
|
|
1161
|
+
while (index < hb_array_size(array)) {
|
|
1162
|
+
AST_NODE_T* item = hb_array_get(array, index);
|
|
1005
1163
|
|
|
1006
1164
|
if (!item) { break; }
|
|
1007
1165
|
|
|
1008
1166
|
if (item->type != AST_ERB_CONTENT_NODE) {
|
|
1009
|
-
|
|
1167
|
+
hb_array_append(new_array, item);
|
|
1010
1168
|
index++;
|
|
1011
1169
|
continue;
|
|
1012
1170
|
}
|
|
@@ -1028,12 +1186,13 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
1028
1186
|
continue;
|
|
1029
1187
|
|
|
1030
1188
|
case CONTROL_TYPE_YIELD: {
|
|
1031
|
-
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);
|
|
1032
1190
|
|
|
1033
1191
|
if (yield_node) {
|
|
1034
|
-
|
|
1192
|
+
ast_node_free((AST_NODE_T*) erb_node);
|
|
1193
|
+
hb_array_append(new_array, yield_node);
|
|
1035
1194
|
} else {
|
|
1036
|
-
|
|
1195
|
+
hb_array_append(new_array, item);
|
|
1037
1196
|
}
|
|
1038
1197
|
|
|
1039
1198
|
index++;
|
|
@@ -1041,7 +1200,7 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
1041
1200
|
}
|
|
1042
1201
|
|
|
1043
1202
|
default:
|
|
1044
|
-
|
|
1203
|
+
hb_array_append(new_array, item);
|
|
1045
1204
|
index++;
|
|
1046
1205
|
break;
|
|
1047
1206
|
}
|
|
@@ -1050,41 +1209,178 @@ static array_T* rewrite_node_array(AST_NODE_T* node, array_T* array, analyze_rub
|
|
|
1050
1209
|
return new_array;
|
|
1051
1210
|
}
|
|
1052
1211
|
|
|
1053
|
-
static bool
|
|
1054
|
-
|
|
1055
|
-
|
|
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
|
+
}
|
|
1270
|
+
|
|
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;
|
|
1056
1338
|
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
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
|
+
}
|
|
1062
1352
|
}
|
|
1063
1353
|
|
|
1064
|
-
if (node->type ==
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
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);
|
|
1069
1358
|
}
|
|
1070
1359
|
|
|
1071
|
-
if (node->type ==
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
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;
|
|
1076
1369
|
}
|
|
1077
1370
|
|
|
1078
|
-
if (node->type ==
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
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;
|
|
1083
1376
|
}
|
|
1084
1377
|
|
|
1085
|
-
|
|
1378
|
+
bool result = true;
|
|
1086
1379
|
|
|
1087
|
-
|
|
1380
|
+
if (is_loop_node) { context->loop_depth--; }
|
|
1381
|
+
if (is_begin_node) { context->rescue_depth--; }
|
|
1382
|
+
|
|
1383
|
+
return result;
|
|
1088
1384
|
}
|
|
1089
1385
|
|
|
1090
1386
|
void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source) {
|
|
@@ -1093,19 +1389,31 @@ void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source)
|
|
|
1093
1389
|
analyze_ruby_context_T* context = malloc(sizeof(analyze_ruby_context_T));
|
|
1094
1390
|
context->document = document;
|
|
1095
1391
|
context->parent = NULL;
|
|
1096
|
-
context->ruby_context_stack =
|
|
1392
|
+
context->ruby_context_stack = hb_array_init(8);
|
|
1097
1393
|
|
|
1098
1394
|
herb_visit_node((AST_NODE_T*) document, transform_erb_nodes, context);
|
|
1099
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
|
+
|
|
1100
1402
|
herb_analyze_parse_errors(document, source);
|
|
1101
1403
|
|
|
1102
|
-
|
|
1404
|
+
herb_parser_match_html_tags_post_analyze(document);
|
|
1405
|
+
|
|
1406
|
+
hb_array_free(&context->ruby_context_stack);
|
|
1407
|
+
|
|
1103
1408
|
free(context);
|
|
1409
|
+
free(invalid_context);
|
|
1104
1410
|
}
|
|
1105
1411
|
|
|
1106
1412
|
void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source) {
|
|
1107
1413
|
char* extracted_ruby = herb_extract_ruby_with_semicolons(source);
|
|
1108
1414
|
|
|
1415
|
+
if (!extracted_ruby) { return; }
|
|
1416
|
+
|
|
1109
1417
|
pm_parser_t parser;
|
|
1110
1418
|
pm_options_t options = { 0, .partial_script = true };
|
|
1111
1419
|
pm_parser_init(&parser, (const uint8_t*) extracted_ruby, strlen(extracted_ruby), &options);
|
|
@@ -1116,7 +1424,7 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source
|
|
|
1116
1424
|
error = (const pm_diagnostic_t*) error->node.next) {
|
|
1117
1425
|
|
|
1118
1426
|
RUBY_PARSE_ERROR_T* parse_error = ruby_parse_error_from_prism_error(error, (AST_NODE_T*) document, source, &parser);
|
|
1119
|
-
|
|
1427
|
+
hb_array_append(document->base.errors, parse_error);
|
|
1120
1428
|
}
|
|
1121
1429
|
|
|
1122
1430
|
pm_node_destroy(&parser, root);
|