herb 0.9.4-arm-linux-gnu → 0.9.6-arm-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/config.yml +57 -21
- data/ext/herb/extension.c +8 -0
- data/ext/herb/extension_helpers.c +1 -0
- data/ext/herb/nodes.c +93 -55
- 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/4.0/herb.so +0 -0
- data/lib/herb/action_view/helper_registry.rb +8107 -0
- data/lib/herb/ast/nodes.rb +212 -78
- data/lib/herb/engine/compiler.rb +4 -6
- data/lib/herb/parser_options.rb +7 -2
- data/lib/herb/project.rb +2 -5
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +8 -2
- data/sig/herb/action_view/helper_registry.rbs +1144 -0
- data/sig/herb/ast/nodes.rbs +85 -34
- data/sig/herb/parser_options.rbs +6 -2
- data/sig/herb/visitor.rbs +5 -2
- data/sig/serialized_ast_nodes.rbs +20 -9
- data/src/analyze/action_view/generated_handlers.c +355 -0
- data/src/analyze/action_view/generated_handlers.h +16 -0
- data/src/analyze/action_view/helper_registry.c +7244 -0
- data/src/analyze/action_view/image_tag.c +4 -31
- data/src/analyze/action_view/javascript_include_tag.c +1 -42
- data/src/analyze/action_view/javascript_tag.c +26 -40
- data/src/analyze/action_view/registry.c +2 -2
- data/src/analyze/action_view/tag_helper_node_builders.c +23 -2
- data/src/analyze/action_view/tag_helpers.c +61 -134
- data/src/analyze/action_view/turbo_frame_tag.c +1 -36
- data/src/analyze/analyze.c +28 -0
- data/src/analyze/analyze_helpers.c +406 -0
- data/src/analyze/builders.c +1 -0
- data/src/analyze/missing_end.c +16 -0
- data/src/analyze/parse_errors.c +3 -2
- data/src/analyze/postfix_conditionals.c +326 -0
- data/src/analyze/render_nodes.c +231 -35
- data/src/analyze/strict_locals.c +22 -338
- data/src/analyze/ternary_conditionals.c +265 -0
- data/src/analyze/transform.c +23 -2
- data/src/ast/ast_nodes.c +114 -57
- data/src/ast/ast_pretty_print.c +109 -25
- data/src/include/analyze/action_view/helper_registry.h +325 -0
- data/src/include/analyze/action_view/tag_helper_handler.h +3 -0
- data/src/include/analyze/action_view/tag_helper_node_builders.h +7 -0
- data/src/include/analyze/action_view/tag_helpers.h +0 -1
- data/src/include/analyze/helpers.h +18 -0
- data/src/include/analyze/postfix_conditionals.h +9 -0
- data/src/include/analyze/ternary_conditionals.h +15 -0
- data/src/include/ast/ast_nodes.h +27 -13
- data/src/include/parser/parser.h +1 -0
- data/src/include/version.h +1 -1
- data/src/parser/match_tags.c +37 -6
- data/src/parser.c +9 -0
- data/src/visitor.c +50 -7
- data/templates/java/org/herb/ast/HelperRegistry.java.erb +258 -0
- data/templates/javascript/packages/core/src/action-view-helpers.ts.erb +171 -0
- data/templates/javascript/packages/core/src/nodes.ts.erb +5 -1
- data/templates/lib/herb/action_view/helper_registry.rb.erb +288 -0
- data/templates/rust/src/action_view_helpers.rs.erb +154 -0
- data/templates/src/analyze/action_view/generated_handlers.c.erb +230 -0
- data/templates/src/analyze/action_view/generated_handlers.h.erb +12 -0
- data/templates/src/analyze/action_view/helper_registry.c.erb +114 -0
- data/templates/src/include/analyze/action_view/helper_registry.h.erb +82 -0
- data/templates/template.rb +338 -1
- metadata +19 -3
- data/src/analyze/action_view/content_tag.c +0 -78
- data/src/analyze/action_view/tag.c +0 -87
|
@@ -1,26 +1,10 @@
|
|
|
1
|
+
#include "../../include/lib/hb_allocator.h"
|
|
2
|
+
#include "../../include/lib/hb_buffer.h"
|
|
3
|
+
|
|
1
4
|
#include <prism.h>
|
|
2
5
|
#include <stdbool.h>
|
|
3
|
-
#include <stdlib.h>
|
|
4
6
|
#include <string.h>
|
|
5
7
|
|
|
6
|
-
#include "../../include/analyze/action_view/tag_helper_handler.h"
|
|
7
|
-
#include "../../include/lib/hb_buffer.h"
|
|
8
|
-
|
|
9
|
-
bool detect_image_tag(pm_call_node_t* call_node, pm_parser_t* parser) {
|
|
10
|
-
if (!call_node || !call_node->name) { return false; }
|
|
11
|
-
|
|
12
|
-
pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
|
|
13
|
-
return constant && constant->length == 9 && strncmp((const char*) constant->start, "image_tag", 9) == 0;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
char* extract_image_tag_name(pm_call_node_t* _call_node, pm_parser_t* _parser, hb_allocator_T* allocator) {
|
|
17
|
-
return hb_allocator_strdup(allocator, "img");
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
char* extract_image_tag_content(pm_call_node_t* _call_node, pm_parser_t* _parser, hb_allocator_T* _allocator) {
|
|
21
|
-
return NULL;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
8
|
char* extract_image_tag_src(pm_call_node_t* call_node, pm_parser_t* _parser, hb_allocator_T* allocator) {
|
|
25
9
|
if (!call_node || !call_node->arguments) { return NULL; }
|
|
26
10
|
|
|
@@ -37,6 +21,7 @@ char* extract_image_tag_src(pm_call_node_t* call_node, pm_parser_t* _parser, hb_
|
|
|
37
21
|
}
|
|
38
22
|
|
|
39
23
|
size_t source_length = first_argument->location.end - first_argument->location.start;
|
|
24
|
+
|
|
40
25
|
return hb_allocator_strndup(allocator, (const char*) first_argument->location.start, source_length);
|
|
41
26
|
}
|
|
42
27
|
|
|
@@ -73,15 +58,3 @@ char* wrap_in_image_path(
|
|
|
73
58
|
|
|
74
59
|
return result;
|
|
75
60
|
}
|
|
76
|
-
|
|
77
|
-
bool image_tag_supports_block(void) {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const tag_helper_handler_T image_tag_handler = { .name = "image_tag",
|
|
82
|
-
.source =
|
|
83
|
-
HB_STRING_LITERAL("ActionView::Helpers::AssetTagHelper#image_tag"),
|
|
84
|
-
.detect = detect_image_tag,
|
|
85
|
-
.extract_tag_name = extract_image_tag_name,
|
|
86
|
-
.extract_content = extract_image_tag_content,
|
|
87
|
-
.supports_block = image_tag_supports_block };
|
|
@@ -1,38 +1,10 @@
|
|
|
1
|
-
#include "../../include/
|
|
1
|
+
#include "../../include/lib/hb_allocator.h"
|
|
2
2
|
#include "../../include/lib/hb_buffer.h"
|
|
3
3
|
|
|
4
4
|
#include <prism.h>
|
|
5
5
|
#include <stdbool.h>
|
|
6
|
-
#include <stdlib.h>
|
|
7
6
|
#include <string.h>
|
|
8
7
|
|
|
9
|
-
bool detect_javascript_include_tag(pm_call_node_t* call_node, pm_parser_t* parser) {
|
|
10
|
-
if (!call_node || !call_node->name) { return false; }
|
|
11
|
-
|
|
12
|
-
pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
|
|
13
|
-
return constant && constant->length == 22
|
|
14
|
-
&& strncmp((const char*) constant->start, "javascript_include_tag", 22) == 0;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
char* extract_javascript_include_tag_name(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
|
|
18
|
-
(void) call_node;
|
|
19
|
-
(void) parser;
|
|
20
|
-
|
|
21
|
-
return hb_allocator_strdup(allocator, "script");
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
char* extract_javascript_include_tag_content(
|
|
25
|
-
pm_call_node_t* call_node,
|
|
26
|
-
pm_parser_t* parser,
|
|
27
|
-
hb_allocator_T* allocator
|
|
28
|
-
) {
|
|
29
|
-
(void) call_node;
|
|
30
|
-
(void) parser;
|
|
31
|
-
(void) allocator;
|
|
32
|
-
|
|
33
|
-
return NULL;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
8
|
char* extract_javascript_include_tag_src(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
|
|
37
9
|
(void) parser;
|
|
38
10
|
|
|
@@ -87,16 +59,3 @@ char* wrap_in_javascript_path(
|
|
|
87
59
|
|
|
88
60
|
return result;
|
|
89
61
|
}
|
|
90
|
-
|
|
91
|
-
bool javascript_include_tag_supports_block(void) {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const tag_helper_handler_T javascript_include_tag_handler = {
|
|
96
|
-
.name = "javascript_include_tag",
|
|
97
|
-
.source = HB_STRING_LITERAL("ActionView::Helpers::AssetTagHelper#javascript_include_tag"),
|
|
98
|
-
.detect = detect_javascript_include_tag,
|
|
99
|
-
.extract_tag_name = extract_javascript_include_tag_name,
|
|
100
|
-
.extract_content = extract_javascript_include_tag_content,
|
|
101
|
-
.supports_block = javascript_include_tag_supports_block
|
|
102
|
-
};
|
|
@@ -1,55 +1,41 @@
|
|
|
1
|
-
#include "../../include/analyze/action_view/
|
|
1
|
+
#include "../../include/analyze/action_view/tag_helper_node_builders.h"
|
|
2
|
+
#include "../../include/ast/ast_nodes.h"
|
|
3
|
+
#include "../../include/lib/hb_array.h"
|
|
4
|
+
#include "../../include/lib/hb_string.h"
|
|
5
|
+
#include "../../include/visitor.h"
|
|
2
6
|
|
|
3
|
-
#include <prism.h>
|
|
4
7
|
#include <stdbool.h>
|
|
5
8
|
#include <stdlib.h>
|
|
6
|
-
#include <string.h>
|
|
7
9
|
|
|
8
|
-
bool
|
|
9
|
-
|
|
10
|
+
bool wrap_javascript_tag_body_visitor(const AST_NODE_T* node, void* data) {
|
|
11
|
+
hb_allocator_T* allocator = (hb_allocator_T*) data;
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
return constant && constant->length == 14 && strncmp((const char*) constant->start, "javascript_tag", 14) == 0;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
char* extract_javascript_tag_name(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
|
|
16
|
-
(void) call_node;
|
|
17
|
-
(void) parser;
|
|
13
|
+
if (node == NULL || node->type != AST_HTML_ELEMENT_NODE) { return true; }
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
}
|
|
15
|
+
AST_HTML_ELEMENT_NODE_T* element = (AST_HTML_ELEMENT_NODE_T*) node;
|
|
21
16
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!call_node || !call_node->arguments) { return NULL; }
|
|
17
|
+
if (!hb_string_equals(element->element_source, hb_string("ActionView::Helpers::JavaScriptHelper#javascript_tag"))) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
if (!arguments->arguments.size) { return NULL; }
|
|
21
|
+
if (element->body == NULL || hb_array_size(element->body) == 0) { return false; }
|
|
29
22
|
|
|
30
|
-
|
|
23
|
+
for (size_t i = 0; i < hb_array_size(element->body); i++) {
|
|
24
|
+
AST_NODE_T* child = (AST_NODE_T*) hb_array_get(element->body, i);
|
|
25
|
+
if (child && child->type == AST_CDATA_NODE) { return false; }
|
|
26
|
+
}
|
|
31
27
|
|
|
32
|
-
|
|
28
|
+
hb_array_T* cdata_children = hb_array_init(hb_array_size(element->body), allocator);
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
size_t length = pm_string_length(&string_node->unescaped);
|
|
37
|
-
return hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
|
|
30
|
+
for (size_t i = 0; i < hb_array_size(element->body); i++) {
|
|
31
|
+
hb_array_append(cdata_children, hb_array_get(element->body, i));
|
|
38
32
|
}
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
34
|
+
AST_CDATA_NODE_T* cdata_node =
|
|
35
|
+
create_javascript_cdata_node(cdata_children, element->base.location.start, element->base.location.end, allocator);
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
37
|
+
element->body->size = 0;
|
|
38
|
+
hb_array_append(element->body, (AST_NODE_T*) cdata_node);
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.source = HB_STRING_LITERAL("ActionView::Helpers::JavaScriptHelper#javascript_tag"),
|
|
51
|
-
.detect = detect_javascript_tag,
|
|
52
|
-
.extract_tag_name = extract_javascript_tag_name,
|
|
53
|
-
.extract_content = extract_javascript_tag_content,
|
|
54
|
-
.supports_block = javascript_tag_supports_block
|
|
55
|
-
};
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
#include <stdlib.h>
|
|
6
6
|
|
|
7
7
|
extern const tag_helper_handler_T content_tag_handler;
|
|
8
|
-
extern const tag_helper_handler_T
|
|
8
|
+
extern const tag_helper_handler_T tag_handler;
|
|
9
9
|
extern const tag_helper_handler_T link_to_handler;
|
|
10
10
|
extern const tag_helper_handler_T turbo_frame_tag_handler;
|
|
11
11
|
extern const tag_helper_handler_T javascript_tag_handler;
|
|
@@ -49,7 +49,7 @@ tag_helper_handler_T* get_tag_helper_handlers(void) {
|
|
|
49
49
|
|
|
50
50
|
if (!initialized) {
|
|
51
51
|
static_handlers[0] = content_tag_handler;
|
|
52
|
-
static_handlers[1] =
|
|
52
|
+
static_handlers[1] = tag_handler;
|
|
53
53
|
static_handlers[2] = link_to_handler;
|
|
54
54
|
static_handlers[3] = turbo_frame_tag_handler;
|
|
55
55
|
static_handlers[4] = javascript_tag_handler;
|
|
@@ -124,7 +124,7 @@ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_node_precise(
|
|
|
124
124
|
open_quote,
|
|
125
125
|
value_children,
|
|
126
126
|
close_quote,
|
|
127
|
-
|
|
127
|
+
true,
|
|
128
128
|
positions->value_start,
|
|
129
129
|
positions->value_end,
|
|
130
130
|
hb_array_init(0, allocator),
|
|
@@ -179,7 +179,7 @@ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_with_ruby_literal_precise(
|
|
|
179
179
|
NULL,
|
|
180
180
|
value_children,
|
|
181
181
|
NULL,
|
|
182
|
-
|
|
182
|
+
true,
|
|
183
183
|
positions->content_start,
|
|
184
184
|
positions->content_end,
|
|
185
185
|
hb_array_init(0, allocator),
|
|
@@ -385,3 +385,24 @@ void append_body_content_node(
|
|
|
385
385
|
if (text_node) { hb_array_append(body, (AST_NODE_T*) text_node); }
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
|
+
|
|
389
|
+
AST_CDATA_NODE_T* create_javascript_cdata_node(
|
|
390
|
+
hb_array_T* children,
|
|
391
|
+
position_T start,
|
|
392
|
+
position_T end,
|
|
393
|
+
hb_allocator_T* allocator
|
|
394
|
+
) {
|
|
395
|
+
token_T* cdata_opening = create_synthetic_token(allocator, "\n//<![CDATA[\n", TOKEN_CDATA_START, start, end);
|
|
396
|
+
|
|
397
|
+
token_T* cdata_closing = create_synthetic_token(allocator, "\n//]]>\n", TOKEN_CDATA_END, start, end);
|
|
398
|
+
|
|
399
|
+
return ast_cdata_node_init(
|
|
400
|
+
cdata_opening,
|
|
401
|
+
children,
|
|
402
|
+
cdata_closing,
|
|
403
|
+
start,
|
|
404
|
+
end,
|
|
405
|
+
hb_array_init(0, allocator),
|
|
406
|
+
allocator
|
|
407
|
+
);
|
|
408
|
+
}
|
|
@@ -45,8 +45,6 @@ typedef struct {
|
|
|
45
45
|
const tag_helper_handler_T* matched_handler;
|
|
46
46
|
const char* original_source;
|
|
47
47
|
size_t erb_content_offset;
|
|
48
|
-
char* condition_source;
|
|
49
|
-
char* condition_type;
|
|
50
48
|
} tag_helper_parse_context_T;
|
|
51
49
|
|
|
52
50
|
static tag_helper_parse_context_T* parse_tag_helper_content(
|
|
@@ -76,15 +74,12 @@ static tag_helper_parse_context_T* parse_tag_helper_content(
|
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
parse_context->info = tag_helper_info_init(allocator);
|
|
79
|
-
parse_context->condition_source = NULL;
|
|
80
|
-
parse_context->condition_type = NULL;
|
|
81
77
|
|
|
82
78
|
tag_helper_search_data_T search = { .tag_helper_node = NULL,
|
|
83
79
|
.source = parse_context->prism_source,
|
|
84
80
|
.parser = &parse_context->parser,
|
|
85
81
|
.info = parse_context->info,
|
|
86
|
-
.found = false
|
|
87
|
-
.postfix_conditional_node = NULL };
|
|
82
|
+
.found = false };
|
|
88
83
|
pm_visit_node(parse_context->root, search_tag_helper_node, &search);
|
|
89
84
|
|
|
90
85
|
if (!search.found) {
|
|
@@ -96,22 +91,6 @@ static tag_helper_parse_context_T* parse_tag_helper_content(
|
|
|
96
91
|
return NULL;
|
|
97
92
|
}
|
|
98
93
|
|
|
99
|
-
if (search.postfix_conditional_node) {
|
|
100
|
-
if (search.postfix_conditional_node->type == PM_IF_NODE) {
|
|
101
|
-
pm_if_node_t* if_node = (pm_if_node_t*) search.postfix_conditional_node;
|
|
102
|
-
size_t predicate_length = if_node->predicate->location.end - if_node->predicate->location.start;
|
|
103
|
-
parse_context->condition_source =
|
|
104
|
-
hb_allocator_strndup(allocator, (const char*) if_node->predicate->location.start, predicate_length);
|
|
105
|
-
parse_context->condition_type = hb_allocator_strdup(allocator, "if");
|
|
106
|
-
} else if (search.postfix_conditional_node->type == PM_UNLESS_NODE) {
|
|
107
|
-
pm_unless_node_t* unless_node = (pm_unless_node_t*) search.postfix_conditional_node;
|
|
108
|
-
size_t predicate_length = unless_node->predicate->location.end - unless_node->predicate->location.start;
|
|
109
|
-
parse_context->condition_source =
|
|
110
|
-
hb_allocator_strndup(allocator, (const char*) unless_node->predicate->location.start, predicate_length);
|
|
111
|
-
parse_context->condition_type = hb_allocator_strdup(allocator, "unless");
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
94
|
parse_context->matched_handler = search.matched_handler;
|
|
116
95
|
return parse_context;
|
|
117
96
|
}
|
|
@@ -131,92 +110,6 @@ static void free_tag_helper_parse_context(tag_helper_parse_context_T* parse_cont
|
|
|
131
110
|
}
|
|
132
111
|
}
|
|
133
112
|
|
|
134
|
-
static AST_NODE_T* wrap_in_conditional_if_needed(
|
|
135
|
-
AST_NODE_T* element,
|
|
136
|
-
tag_helper_parse_context_T* parse_context,
|
|
137
|
-
hb_allocator_T* allocator
|
|
138
|
-
) {
|
|
139
|
-
if (!element || !parse_context || !parse_context->condition_source || !parse_context->condition_type) {
|
|
140
|
-
return element;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
position_T start = element->location.start;
|
|
144
|
-
position_T end = element->location.end;
|
|
145
|
-
|
|
146
|
-
hb_buffer_T content_buffer;
|
|
147
|
-
hb_buffer_init(&content_buffer, 64, allocator);
|
|
148
|
-
hb_buffer_append(&content_buffer, " ");
|
|
149
|
-
hb_buffer_append(&content_buffer, parse_context->condition_type);
|
|
150
|
-
hb_buffer_append(&content_buffer, " ");
|
|
151
|
-
hb_buffer_append(&content_buffer, parse_context->condition_source);
|
|
152
|
-
hb_buffer_append(&content_buffer, " ");
|
|
153
|
-
const char* content_string = hb_buffer_value(&content_buffer);
|
|
154
|
-
|
|
155
|
-
token_T* tag_opening = create_synthetic_token(allocator, "<%", TOKEN_ERB_START, start, start);
|
|
156
|
-
token_T* content_token = create_synthetic_token(allocator, content_string, TOKEN_ERB_CONTENT, start, end);
|
|
157
|
-
token_T* tag_closing = create_synthetic_token(allocator, "%>", TOKEN_ERB_END, end, end);
|
|
158
|
-
|
|
159
|
-
hb_array_T* statements = hb_array_init(1, allocator);
|
|
160
|
-
hb_array_append(statements, element);
|
|
161
|
-
|
|
162
|
-
token_T* end_opening = create_synthetic_token(allocator, "<%", TOKEN_ERB_START, end, end);
|
|
163
|
-
token_T* end_content = create_synthetic_token(allocator, " end ", TOKEN_ERB_CONTENT, end, end);
|
|
164
|
-
token_T* end_closing = create_synthetic_token(allocator, "%>", TOKEN_ERB_END, end, end);
|
|
165
|
-
|
|
166
|
-
AST_ERB_END_NODE_T* end_node =
|
|
167
|
-
ast_erb_end_node_init(end_opening, end_content, end_closing, end, end, hb_array_init(0, allocator), allocator);
|
|
168
|
-
|
|
169
|
-
herb_prism_node_T empty_prism_node = HERB_PRISM_NODE_EMPTY;
|
|
170
|
-
|
|
171
|
-
if (strcmp(parse_context->condition_type, "if") == 0) {
|
|
172
|
-
AST_ERB_IF_NODE_T* if_node = ast_erb_if_node_init(
|
|
173
|
-
tag_opening,
|
|
174
|
-
content_token,
|
|
175
|
-
tag_closing,
|
|
176
|
-
NULL,
|
|
177
|
-
empty_prism_node,
|
|
178
|
-
statements,
|
|
179
|
-
NULL,
|
|
180
|
-
end_node,
|
|
181
|
-
start,
|
|
182
|
-
end,
|
|
183
|
-
hb_array_init(0, allocator),
|
|
184
|
-
allocator
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
return (AST_NODE_T*) if_node;
|
|
188
|
-
} else {
|
|
189
|
-
AST_ERB_UNLESS_NODE_T* unless_node = ast_erb_unless_node_init(
|
|
190
|
-
tag_opening,
|
|
191
|
-
content_token,
|
|
192
|
-
tag_closing,
|
|
193
|
-
NULL,
|
|
194
|
-
empty_prism_node,
|
|
195
|
-
statements,
|
|
196
|
-
NULL,
|
|
197
|
-
end_node,
|
|
198
|
-
start,
|
|
199
|
-
end,
|
|
200
|
-
hb_array_init(0, allocator),
|
|
201
|
-
allocator
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
return (AST_NODE_T*) unless_node;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
static bool is_postfix_if_node(const pm_node_t* node) {
|
|
209
|
-
if (node->type != PM_IF_NODE) { return false; }
|
|
210
|
-
pm_if_node_t* if_node = (pm_if_node_t*) node;
|
|
211
|
-
return if_node->if_keyword_loc.start != NULL && if_node->end_keyword_loc.start == NULL;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
static bool is_postfix_unless_node(const pm_node_t* node) {
|
|
215
|
-
if (node->type != PM_UNLESS_NODE) { return false; }
|
|
216
|
-
pm_unless_node_t* unless_node = (pm_unless_node_t*) node;
|
|
217
|
-
return unless_node->keyword_loc.start != NULL && unless_node->end_keyword_loc.start == NULL;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
113
|
bool search_tag_helper_node(const pm_node_t* node, void* data) {
|
|
221
114
|
tag_helper_search_data_T* search_data = (tag_helper_search_data_T*) data;
|
|
222
115
|
|
|
@@ -247,16 +140,6 @@ bool search_tag_helper_node(const pm_node_t* node, void* data) {
|
|
|
247
140
|
return false;
|
|
248
141
|
}
|
|
249
142
|
|
|
250
|
-
if (is_postfix_if_node(node) || is_postfix_unless_node(node)) {
|
|
251
|
-
const pm_node_t* saved = search_data->postfix_conditional_node;
|
|
252
|
-
search_data->postfix_conditional_node = node;
|
|
253
|
-
pm_visit_child_nodes(node, search_tag_helper_node, search_data);
|
|
254
|
-
|
|
255
|
-
if (!search_data->found) { search_data->postfix_conditional_node = saved; }
|
|
256
|
-
|
|
257
|
-
return search_data->found;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
143
|
pm_visit_child_nodes(node, search_tag_helper_node, search_data);
|
|
261
144
|
|
|
262
145
|
return search_data->found;
|
|
@@ -639,7 +522,15 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
639
522
|
id_is_ruby_expression ? create_html_attribute_with_ruby_literal("id", id_value, id_start, id_end, allocator)
|
|
640
523
|
: create_html_attribute_node("id", id_value, id_start, id_end, allocator);
|
|
641
524
|
|
|
642
|
-
if (id_attribute) {
|
|
525
|
+
if (id_attribute) {
|
|
526
|
+
AST_NODE_T* src_node = remove_attribute_by_name(attributes, "src");
|
|
527
|
+
AST_NODE_T* target_node = remove_attribute_by_name(attributes, "target");
|
|
528
|
+
|
|
529
|
+
hb_array_append(attributes, (AST_NODE_T*) id_attribute);
|
|
530
|
+
|
|
531
|
+
if (src_node) { hb_array_append(attributes, src_node); }
|
|
532
|
+
if (target_node) { hb_array_append(attributes, target_node); }
|
|
533
|
+
}
|
|
643
534
|
|
|
644
535
|
hb_allocator_dealloc(allocator, id_value);
|
|
645
536
|
}
|
|
@@ -679,7 +570,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
679
570
|
? create_html_attribute_node("src", source_attribute_value, source_start, source_end, allocator)
|
|
680
571
|
: create_html_attribute_with_ruby_literal("src", source_attribute_value, source_start, source_end, allocator);
|
|
681
572
|
|
|
682
|
-
if (source_attribute) {
|
|
573
|
+
if (source_attribute) { hb_array_append(attributes, (AST_NODE_T*) source_attribute); }
|
|
683
574
|
|
|
684
575
|
if (source_attribute_value != source_value) { hb_allocator_dealloc(allocator, source_attribute_value); }
|
|
685
576
|
hb_allocator_dealloc(allocator, source_value);
|
|
@@ -723,7 +614,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
723
614
|
? create_html_attribute_node("src", source_attribute_value, source_start, source_end, allocator)
|
|
724
615
|
: create_html_attribute_with_ruby_literal("src", source_attribute_value, source_start, source_end, allocator);
|
|
725
616
|
|
|
726
|
-
if (source_attribute) {
|
|
617
|
+
if (source_attribute) { hb_array_append(attributes, (AST_NODE_T*) source_attribute); }
|
|
727
618
|
if (source_attribute_value != source_value) { hb_allocator_dealloc(allocator, source_attribute_value); }
|
|
728
619
|
|
|
729
620
|
hb_allocator_dealloc(allocator, source_value);
|
|
@@ -798,14 +689,37 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
798
689
|
);
|
|
799
690
|
}
|
|
800
691
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
692
|
+
if (string_equals(handler->name, "javascript_tag")) {
|
|
693
|
+
hb_array_T* cdata_children = hb_array_init(1, allocator);
|
|
694
|
+
|
|
695
|
+
append_body_content_node(
|
|
696
|
+
cdata_children,
|
|
697
|
+
helper_content,
|
|
698
|
+
content_is_ruby_expression,
|
|
699
|
+
erb_node->base.location.start,
|
|
700
|
+
erb_node->base.location.end,
|
|
701
|
+
allocator
|
|
702
|
+
);
|
|
703
|
+
|
|
704
|
+
AST_CDATA_NODE_T* cdata_node = create_javascript_cdata_node(
|
|
705
|
+
cdata_children,
|
|
706
|
+
erb_node->base.location.start,
|
|
707
|
+
erb_node->base.location.end,
|
|
708
|
+
allocator
|
|
709
|
+
);
|
|
710
|
+
|
|
711
|
+
if (cdata_node) { hb_array_append(body, (AST_NODE_T*) cdata_node); }
|
|
712
|
+
} else {
|
|
713
|
+
append_body_content_node(
|
|
714
|
+
body,
|
|
715
|
+
helper_content,
|
|
716
|
+
content_is_ruby_expression,
|
|
717
|
+
erb_node->base.location.start,
|
|
718
|
+
erb_node->base.location.end,
|
|
719
|
+
allocator
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
|
|
809
723
|
hb_allocator_dealloc(allocator, helper_content);
|
|
810
724
|
}
|
|
811
725
|
|
|
@@ -1117,7 +1031,7 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
|
|
|
1117
1031
|
AST_HTML_ATTRIBUTE_NODE_T* href_attribute =
|
|
1118
1032
|
create_href_attribute(href, href_is_ruby_expression, href_start, href_end, allocator);
|
|
1119
1033
|
|
|
1120
|
-
if (href_attribute) {
|
|
1034
|
+
if (href_attribute) { hb_array_append(attributes, (AST_NODE_T*) href_attribute); }
|
|
1121
1035
|
|
|
1122
1036
|
hb_allocator_dealloc(allocator, href);
|
|
1123
1037
|
}
|
|
@@ -1138,7 +1052,15 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
|
|
|
1138
1052
|
id_is_ruby_expression ? create_html_attribute_with_ruby_literal("id", id_value, id_start, id_end, allocator)
|
|
1139
1053
|
: create_html_attribute_node("id", id_value, id_start, id_end, allocator);
|
|
1140
1054
|
|
|
1141
|
-
if (id_attribute) {
|
|
1055
|
+
if (id_attribute) {
|
|
1056
|
+
AST_NODE_T* src_node = remove_attribute_by_name(attributes, "src");
|
|
1057
|
+
AST_NODE_T* target_node = remove_attribute_by_name(attributes, "target");
|
|
1058
|
+
|
|
1059
|
+
hb_array_append(attributes, (AST_NODE_T*) id_attribute);
|
|
1060
|
+
|
|
1061
|
+
if (src_node) { hb_array_append(attributes, src_node); }
|
|
1062
|
+
if (target_node) { hb_array_append(attributes, target_node); }
|
|
1063
|
+
}
|
|
1142
1064
|
|
|
1143
1065
|
hb_allocator_dealloc(allocator, id_value);
|
|
1144
1066
|
}
|
|
@@ -1395,7 +1317,7 @@ static AST_NODE_T* transform_link_to_helper(
|
|
|
1395
1317
|
AST_HTML_ATTRIBUTE_NODE_T* href_attribute =
|
|
1396
1318
|
create_href_attribute(href, href_is_ruby_expression, href_start, href_end, allocator);
|
|
1397
1319
|
|
|
1398
|
-
if (href_attribute) {
|
|
1320
|
+
if (href_attribute) { hb_array_append(attributes, (AST_NODE_T*) href_attribute); }
|
|
1399
1321
|
if (!info->content) {
|
|
1400
1322
|
href_for_body = hb_allocator_strdup(allocator, href);
|
|
1401
1323
|
href_for_body_is_ruby_expression = href_is_ruby_expression;
|
|
@@ -1503,6 +1425,12 @@ void transform_tag_helper_array(hb_array_T* array, analyze_ruby_context_T* conte
|
|
|
1503
1425
|
|
|
1504
1426
|
if (child->type == AST_ERB_BLOCK_NODE) {
|
|
1505
1427
|
AST_ERB_BLOCK_NODE_T* block_node = (AST_ERB_BLOCK_NODE_T*) child;
|
|
1428
|
+
|
|
1429
|
+
if (block_node->tag_opening && !hb_string_is_empty(block_node->tag_opening->value)) {
|
|
1430
|
+
const char* opening_string = block_node->tag_opening->value.data;
|
|
1431
|
+
if (opening_string && strstr(opening_string, "=") == NULL) { continue; }
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1506
1434
|
token_T* block_content = block_node->content;
|
|
1507
1435
|
|
|
1508
1436
|
if (block_content && !hb_string_is_empty(block_content->value)) {
|
|
@@ -1518,7 +1446,6 @@ void transform_tag_helper_array(hb_array_T* array, analyze_ruby_context_T* conte
|
|
|
1518
1446
|
|
|
1519
1447
|
if (parse_context) {
|
|
1520
1448
|
replacement = transform_erb_block_to_tag_helper(block_node, context, parse_context);
|
|
1521
|
-
replacement = wrap_in_conditional_if_needed(replacement, parse_context, context->allocator);
|
|
1522
1449
|
free_tag_helper_parse_context(parse_context);
|
|
1523
1450
|
}
|
|
1524
1451
|
|
|
@@ -1532,6 +1459,7 @@ void transform_tag_helper_array(hb_array_T* array, analyze_ruby_context_T* conte
|
|
|
1532
1459
|
const char* opening_string = tag_opening->value.data;
|
|
1533
1460
|
|
|
1534
1461
|
if (opening_string && strstr(opening_string, "#") != NULL) { continue; }
|
|
1462
|
+
if (opening_string && strstr(opening_string, "=") == NULL) { continue; }
|
|
1535
1463
|
}
|
|
1536
1464
|
|
|
1537
1465
|
token_T* erb_content = erb_node->content;
|
|
@@ -1615,7 +1543,6 @@ void transform_tag_helper_array(hb_array_T* array, analyze_ruby_context_T* conte
|
|
|
1615
1543
|
replacement = transform_tag_helper_with_attributes(erb_node, context, parse_context);
|
|
1616
1544
|
}
|
|
1617
1545
|
|
|
1618
|
-
replacement = wrap_in_conditional_if_needed(replacement, parse_context, context->allocator);
|
|
1619
1546
|
free_tag_helper_parse_context(parse_context);
|
|
1620
1547
|
}
|
|
1621
1548
|
|
|
@@ -1,32 +1,9 @@
|
|
|
1
|
-
#include "../../include/
|
|
1
|
+
#include "../../include/lib/hb_allocator.h"
|
|
2
2
|
|
|
3
3
|
#include <prism.h>
|
|
4
4
|
#include <stdbool.h>
|
|
5
|
-
#include <stdlib.h>
|
|
6
5
|
#include <string.h>
|
|
7
6
|
|
|
8
|
-
bool detect_turbo_frame_tag(pm_call_node_t* call_node, pm_parser_t* parser) {
|
|
9
|
-
if (!call_node || !call_node->name) { return false; }
|
|
10
|
-
|
|
11
|
-
pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
|
|
12
|
-
return constant && constant->length == 15 && strncmp((const char*) constant->start, "turbo_frame_tag", 15) == 0;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
char* extract_turbo_frame_tag_name(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
|
|
16
|
-
(void) call_node;
|
|
17
|
-
(void) parser;
|
|
18
|
-
|
|
19
|
-
return hb_allocator_strdup(allocator, "turbo-frame");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
char* extract_turbo_frame_tag_content(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
|
|
23
|
-
(void) call_node;
|
|
24
|
-
(void) parser;
|
|
25
|
-
(void) allocator;
|
|
26
|
-
|
|
27
|
-
return NULL;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
7
|
char* extract_turbo_frame_tag_id(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
|
|
31
8
|
if (!call_node || !call_node->arguments) { return NULL; }
|
|
32
9
|
|
|
@@ -74,15 +51,3 @@ char* extract_turbo_frame_tag_id(pm_call_node_t* call_node, pm_parser_t* parser,
|
|
|
74
51
|
|
|
75
52
|
return result;
|
|
76
53
|
}
|
|
77
|
-
|
|
78
|
-
bool turbo_frame_tag_supports_block(void) {
|
|
79
|
-
return true;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const tag_helper_handler_T turbo_frame_tag_handler = { .name = "turbo_frame_tag",
|
|
83
|
-
.source =
|
|
84
|
-
HB_STRING_LITERAL("Turbo::FramesHelper#turbo_frame_tag"),
|
|
85
|
-
.detect = detect_turbo_frame_tag,
|
|
86
|
-
.extract_tag_name = extract_turbo_frame_tag_name,
|
|
87
|
-
.extract_content = extract_turbo_frame_tag_content,
|
|
88
|
-
.supports_block = turbo_frame_tag_supports_block };
|
data/src/analyze/analyze.c
CHANGED
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
#include "../include/analyze/control_type.h"
|
|
9
9
|
#include "../include/analyze/helpers.h"
|
|
10
10
|
#include "../include/analyze/invalid_structures.h"
|
|
11
|
+
#include "../include/analyze/postfix_conditionals.h"
|
|
11
12
|
#include "../include/analyze/render_nodes.h"
|
|
12
13
|
#include "../include/analyze/strict_locals.h"
|
|
14
|
+
#include "../include/analyze/ternary_conditionals.h"
|
|
13
15
|
#include "../include/ast/ast_node.h"
|
|
14
16
|
#include "../include/ast/ast_nodes.h"
|
|
15
17
|
#include "../include/errors.h"
|
|
@@ -736,12 +738,32 @@ static size_t process_block_structure(
|
|
|
736
738
|
hb_array_T* block_errors = erb_node->base.errors;
|
|
737
739
|
erb_node->base.errors = NULL;
|
|
738
740
|
|
|
741
|
+
// Filter out "incomplete block" Prism errors since we've matched the block with its end tag.
|
|
742
|
+
if (block_errors) {
|
|
743
|
+
for (size_t error_index = hb_array_size(block_errors); error_index > 0; error_index--) {
|
|
744
|
+
ERROR_T* error = hb_array_get(block_errors, error_index - 1);
|
|
745
|
+
if (!error || error->type != RUBY_PARSE_ERROR) { continue; }
|
|
746
|
+
|
|
747
|
+
RUBY_PARSE_ERROR_T* parse_error = (RUBY_PARSE_ERROR_T*) error;
|
|
748
|
+
|
|
749
|
+
if (string_equals(parse_error->diagnostic_id.data, "block_term_end")
|
|
750
|
+
|| string_equals(parse_error->diagnostic_id.data, "block_term_brace")
|
|
751
|
+
|| string_equals(parse_error->diagnostic_id.data, "unexpected_token_close_context")) {
|
|
752
|
+
hb_array_remove(block_errors, error_index - 1);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
hb_array_T* block_arguments =
|
|
758
|
+
extract_block_arguments_from_erb_node(erb_node, context->source, block_errors, allocator);
|
|
759
|
+
|
|
739
760
|
AST_ERB_BLOCK_NODE_T* block_node = ast_erb_block_node_init(
|
|
740
761
|
erb_node->tag_opening,
|
|
741
762
|
erb_node->content,
|
|
742
763
|
erb_node->tag_closing,
|
|
743
764
|
HERB_PRISM_NODE_EMPTY,
|
|
744
765
|
children,
|
|
766
|
+
block_arguments,
|
|
745
767
|
rescue_clause,
|
|
746
768
|
else_clause,
|
|
747
769
|
ensure_clause,
|
|
@@ -942,6 +964,7 @@ hb_array_T* get_node_children_array(const AST_NODE_T* node) {
|
|
|
942
964
|
case AST_ERB_ENSURE_NODE: return ((AST_ERB_ENSURE_NODE_T*) node)->statements;
|
|
943
965
|
case AST_ERB_CASE_NODE: return ((AST_ERB_CASE_NODE_T*) node)->children;
|
|
944
966
|
case AST_ERB_WHEN_NODE: return ((AST_ERB_WHEN_NODE_T*) node)->statements;
|
|
967
|
+
case AST_ERB_RENDER_NODE: return ((AST_ERB_RENDER_NODE_T*) node)->body;
|
|
945
968
|
default: return NULL;
|
|
946
969
|
}
|
|
947
970
|
}
|
|
@@ -1008,6 +1031,11 @@ void herb_analyze_parse_tree(
|
|
|
1008
1031
|
.source = source,
|
|
1009
1032
|
};
|
|
1010
1033
|
|
|
1034
|
+
if (options && (options->transform_conditionals || options->action_view_helpers)) {
|
|
1035
|
+
herb_visit_node((AST_NODE_T*) document, transform_conditional_nodes, &context);
|
|
1036
|
+
herb_visit_node((AST_NODE_T*) document, transform_ternary_conditional_nodes, &context);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1011
1039
|
herb_visit_node((AST_NODE_T*) document, transform_erb_nodes, &context);
|
|
1012
1040
|
|
|
1013
1041
|
if (options && options->render_nodes) { herb_visit_node((AST_NODE_T*) document, transform_render_nodes, &context); }
|