herb 0.9.4-aarch64-linux-gnu → 0.9.5-aarch64-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/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/ast/nodes.rb +212 -78
- data/lib/herb/engine/compiler.rb +4 -6
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +8 -2
- data/sig/herb/ast/nodes.rbs +85 -34
- data/sig/herb/visitor.rbs +5 -2
- data/sig/serialized_ast_nodes.rbs +20 -9
- data/src/analyze/action_view/javascript_tag.c +38 -0
- data/src/analyze/action_view/tag_helper_node_builders.c +23 -2
- data/src/analyze/action_view/tag_helpers.c +53 -14
- data/src/analyze/analyze.c +21 -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/render_nodes.c +231 -35
- data/src/analyze/strict_locals.c +22 -338
- 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/tag_helper_handler.h +3 -0
- data/src/include/analyze/action_view/tag_helper_node_builders.h +7 -0
- data/src/include/analyze/helpers.h +18 -0
- data/src/include/ast/ast_nodes.h +27 -13
- data/src/include/version.h +1 -1
- data/src/parser/match_tags.c +37 -6
- data/src/parser.c +8 -0
- data/src/visitor.c +50 -7
- metadata +1 -1
data/src/analyze/render_nodes.c
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include "../include/analyze/action_view/tag_helper_node_builders.h"
|
|
3
3
|
#include "../include/analyze/action_view/tag_helpers.h"
|
|
4
4
|
#include "../include/analyze/analyze.h"
|
|
5
|
+
#include "../include/analyze/helpers.h"
|
|
5
6
|
#include "../include/ast/ast_nodes.h"
|
|
6
7
|
#include "../include/errors.h"
|
|
7
8
|
#include "../include/lib/hb_allocator.h"
|
|
@@ -14,6 +15,16 @@
|
|
|
14
15
|
#include <stdbool.h>
|
|
15
16
|
#include <string.h>
|
|
16
17
|
|
|
18
|
+
static token_T* create_token_from_prism_node(
|
|
19
|
+
pm_node_t* node,
|
|
20
|
+
const char* value,
|
|
21
|
+
token_type_T type,
|
|
22
|
+
const char* source,
|
|
23
|
+
size_t erb_content_offset,
|
|
24
|
+
const uint8_t* erb_content_source,
|
|
25
|
+
hb_allocator_T* allocator
|
|
26
|
+
);
|
|
27
|
+
|
|
17
28
|
typedef struct {
|
|
18
29
|
char* value;
|
|
19
30
|
pm_node_t* value_node;
|
|
@@ -62,6 +73,27 @@ static pm_call_node_t* find_render_call(pm_node_t* node, pm_parser_t* parser) {
|
|
|
62
73
|
return NULL;
|
|
63
74
|
}
|
|
64
75
|
|
|
76
|
+
static pm_block_node_t* find_block_on_render_call(pm_call_node_t* render_call) {
|
|
77
|
+
if (!render_call) { return NULL; }
|
|
78
|
+
|
|
79
|
+
if (render_call->block && render_call->block->type == PM_BLOCK_NODE) { return (pm_block_node_t*) render_call->block; }
|
|
80
|
+
|
|
81
|
+
pm_arguments_node_t* arguments = render_call->arguments;
|
|
82
|
+
if (!arguments || arguments->arguments.size == 0) { return NULL; }
|
|
83
|
+
|
|
84
|
+
pm_node_t* first_argument = arguments->arguments.nodes[0];
|
|
85
|
+
|
|
86
|
+
if (first_argument->type == PM_CALL_NODE) {
|
|
87
|
+
pm_call_node_t* argument_call = (pm_call_node_t*) first_argument;
|
|
88
|
+
|
|
89
|
+
if (argument_call->block && argument_call->block->type == PM_BLOCK_NODE) {
|
|
90
|
+
return (pm_block_node_t*) argument_call->block;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return NULL;
|
|
95
|
+
}
|
|
96
|
+
|
|
65
97
|
static char* extract_string_value(pm_node_t* node, hb_allocator_T* allocator) {
|
|
66
98
|
if (!node) { return NULL; }
|
|
67
99
|
|
|
@@ -274,6 +306,15 @@ static token_T* extract_keyword_token(
|
|
|
274
306
|
return token;
|
|
275
307
|
}
|
|
276
308
|
|
|
309
|
+
typedef struct {
|
|
310
|
+
hb_array_T* block_body;
|
|
311
|
+
hb_array_T* block_arguments;
|
|
312
|
+
AST_ERB_RESCUE_NODE_T* rescue_clause;
|
|
313
|
+
AST_ERB_ELSE_NODE_T* else_clause;
|
|
314
|
+
AST_ERB_ENSURE_NODE_T* ensure_clause;
|
|
315
|
+
AST_ERB_END_NODE_T* end_node;
|
|
316
|
+
} render_block_fields_T;
|
|
317
|
+
|
|
277
318
|
static AST_ERB_RENDER_NODE_T* create_render_node_from_call(
|
|
278
319
|
AST_ERB_CONTENT_NODE_T* erb_node,
|
|
279
320
|
pm_call_node_t* call_node,
|
|
@@ -281,9 +322,9 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call(
|
|
|
281
322
|
const char* source,
|
|
282
323
|
size_t erb_content_offset,
|
|
283
324
|
const uint8_t* erb_content_source,
|
|
325
|
+
render_block_fields_T* block_fields,
|
|
284
326
|
hb_allocator_T* allocator
|
|
285
327
|
) {
|
|
286
|
-
(void) parser;
|
|
287
328
|
|
|
288
329
|
pm_arguments_node_t* arguments = call_node->arguments;
|
|
289
330
|
pm_keyword_hash_node_t* keyword_hash = arguments ? find_keyword_hash(arguments) : NULL;
|
|
@@ -626,12 +667,68 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call(
|
|
|
626
667
|
|
|
627
668
|
herb_prism_node_T prism_node = erb_node->prism_node;
|
|
628
669
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
670
|
+
hb_array_T* render_block_body = block_fields ? block_fields->block_body : NULL;
|
|
671
|
+
hb_array_T* render_block_arguments = block_fields ? block_fields->block_arguments : NULL;
|
|
672
|
+
|
|
673
|
+
AST_ERB_RESCUE_NODE_T* render_rescue_clause = block_fields ? block_fields->rescue_clause : NULL;
|
|
674
|
+
AST_ERB_ELSE_NODE_T* render_else_clause = block_fields ? block_fields->else_clause : NULL;
|
|
675
|
+
AST_ERB_ENSURE_NODE_T* render_ensure_clause = block_fields ? block_fields->ensure_clause : NULL;
|
|
676
|
+
AST_ERB_END_NODE_T* render_end_node = block_fields ? block_fields->end_node : NULL;
|
|
677
|
+
|
|
678
|
+
if (!render_block_body) { render_block_body = hb_array_init(0, allocator); }
|
|
679
|
+
if (!render_block_arguments) { render_block_arguments = hb_array_init(0, allocator); }
|
|
680
|
+
|
|
681
|
+
if (!block_fields) {
|
|
682
|
+
pm_block_node_t* inline_block = find_block_on_render_call(call_node);
|
|
683
|
+
|
|
684
|
+
if (inline_block) {
|
|
685
|
+
const uint8_t* content_source = erb_content_source ? erb_content_source : (const uint8_t*) parser->start;
|
|
686
|
+
|
|
687
|
+
if (inline_block->parameters && inline_block->parameters->type == PM_BLOCK_PARAMETERS_NODE) {
|
|
688
|
+
pm_block_parameters_node_t* block_parameters = (pm_block_parameters_node_t*) inline_block->parameters;
|
|
689
|
+
|
|
690
|
+
render_block_arguments = extract_parameters_from_prism(
|
|
691
|
+
block_parameters->parameters,
|
|
692
|
+
parser,
|
|
693
|
+
source,
|
|
694
|
+
erb_content_offset,
|
|
695
|
+
content_source,
|
|
696
|
+
allocator
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (inline_block->body) {
|
|
701
|
+
size_t body_length = (size_t) (inline_block->body->location.end - inline_block->body->location.start);
|
|
702
|
+
char* body_source =
|
|
703
|
+
hb_allocator_strndup(allocator, (const char*) inline_block->body->location.start, body_length);
|
|
704
|
+
|
|
705
|
+
position_T body_start = { .line = 1, .column = 1 };
|
|
706
|
+
position_T body_end = { .line = 1, .column = 1 };
|
|
707
|
+
|
|
708
|
+
if (source && content_source) {
|
|
709
|
+
size_t start_offset = (size_t) (inline_block->body->location.start - content_source);
|
|
710
|
+
size_t end_offset = (size_t) (inline_block->body->location.end - content_source);
|
|
711
|
+
body_start = byte_offset_to_position(source, erb_content_offset + start_offset);
|
|
712
|
+
body_end = byte_offset_to_position(source, erb_content_offset + end_offset);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
AST_RUBY_LITERAL_NODE_T* body_node = ast_ruby_literal_node_init(
|
|
716
|
+
hb_string_from_c_string(body_source),
|
|
717
|
+
body_start,
|
|
718
|
+
body_end,
|
|
719
|
+
hb_array_init(0, allocator),
|
|
720
|
+
allocator
|
|
721
|
+
);
|
|
722
|
+
|
|
723
|
+
render_block_body = hb_array_init(1, allocator);
|
|
724
|
+
hb_array_append(render_block_body, body_node);
|
|
725
|
+
|
|
726
|
+
hb_allocator_dealloc(allocator, body_source);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
AST_RUBY_RENDER_KEYWORDS_NODE_T* keywords_node = ast_ruby_render_keywords_node_init(
|
|
635
732
|
partial,
|
|
636
733
|
template_path,
|
|
637
734
|
layout,
|
|
@@ -652,6 +749,25 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call(
|
|
|
652
749
|
locals,
|
|
653
750
|
erb_node->base.location.start,
|
|
654
751
|
erb_node->base.location.end,
|
|
752
|
+
hb_array_init(0, allocator),
|
|
753
|
+
allocator
|
|
754
|
+
);
|
|
755
|
+
|
|
756
|
+
AST_ERB_RENDER_NODE_T* render_node = ast_erb_render_node_init(
|
|
757
|
+
erb_node->tag_opening,
|
|
758
|
+
erb_node->content,
|
|
759
|
+
erb_node->tag_closing,
|
|
760
|
+
erb_node->analyzed_ruby,
|
|
761
|
+
prism_node,
|
|
762
|
+
keywords_node,
|
|
763
|
+
render_block_body,
|
|
764
|
+
render_block_arguments,
|
|
765
|
+
render_rescue_clause,
|
|
766
|
+
render_else_clause,
|
|
767
|
+
render_ensure_clause,
|
|
768
|
+
render_end_node,
|
|
769
|
+
erb_node->base.location.start,
|
|
770
|
+
erb_node->base.location.end,
|
|
655
771
|
errors,
|
|
656
772
|
allocator
|
|
657
773
|
);
|
|
@@ -682,43 +798,123 @@ static size_t calculate_byte_offset_from_pos(const char* source, position_T posi
|
|
|
682
798
|
return offset;
|
|
683
799
|
}
|
|
684
800
|
|
|
685
|
-
static
|
|
686
|
-
if (!
|
|
801
|
+
static bool is_erb_comment_tag(token_T* tag_opening) {
|
|
802
|
+
if (!tag_opening || hb_string_is_empty(tag_opening->value)) { return false; }
|
|
687
803
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
804
|
+
const char* opening_string = tag_opening->value.data;
|
|
805
|
+
return opening_string && strstr(opening_string, "#") != NULL;
|
|
806
|
+
}
|
|
691
807
|
|
|
692
|
-
|
|
808
|
+
static AST_ERB_RENDER_NODE_T* try_transform_content_node(
|
|
809
|
+
AST_ERB_CONTENT_NODE_T* erb_node,
|
|
810
|
+
analyze_ruby_context_T* context
|
|
811
|
+
) {
|
|
812
|
+
if (!erb_node->analyzed_ruby || !erb_node->analyzed_ruby->valid || !erb_node->analyzed_ruby->parsed) { return NULL; }
|
|
813
|
+
if (is_erb_comment_tag(erb_node->tag_opening)) { return NULL; }
|
|
693
814
|
|
|
694
|
-
|
|
815
|
+
pm_call_node_t* render_call = find_render_call(erb_node->analyzed_ruby->root, &erb_node->analyzed_ruby->parser);
|
|
816
|
+
if (!render_call) { return NULL; }
|
|
695
817
|
|
|
696
|
-
|
|
818
|
+
size_t erb_content_offset = 0;
|
|
697
819
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
}
|
|
820
|
+
if (context->source && erb_node->content) {
|
|
821
|
+
erb_content_offset = calculate_byte_offset_from_pos(context->source, erb_node->content->location.start);
|
|
822
|
+
}
|
|
702
823
|
|
|
703
|
-
|
|
704
|
-
if (!render_call) { continue; }
|
|
824
|
+
const uint8_t* erb_content_source = (const uint8_t*) erb_node->analyzed_ruby->parser.start;
|
|
705
825
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
826
|
+
return create_render_node_from_call(
|
|
827
|
+
erb_node,
|
|
828
|
+
render_call,
|
|
829
|
+
&erb_node->analyzed_ruby->parser,
|
|
830
|
+
context->source,
|
|
831
|
+
erb_content_offset,
|
|
832
|
+
erb_content_source,
|
|
833
|
+
NULL,
|
|
834
|
+
context->allocator
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
static AST_ERB_RENDER_NODE_T* try_transform_block_node(
|
|
839
|
+
AST_ERB_BLOCK_NODE_T* block_node,
|
|
840
|
+
analyze_ruby_context_T* context
|
|
841
|
+
) {
|
|
842
|
+
if (!block_node->content || hb_string_is_empty(block_node->content->value)) { return NULL; }
|
|
710
843
|
|
|
711
|
-
|
|
844
|
+
const char* ruby_source = block_node->content->value.data;
|
|
845
|
+
size_t ruby_length = block_node->content->value.length;
|
|
712
846
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
);
|
|
847
|
+
pm_parser_t parser;
|
|
848
|
+
pm_parser_init(&parser, (const uint8_t*) ruby_source, ruby_length, NULL);
|
|
849
|
+
pm_node_t* root = pm_parse(&parser);
|
|
850
|
+
|
|
851
|
+
pm_call_node_t* render_call = find_render_call(root, &parser);
|
|
852
|
+
|
|
853
|
+
if (!render_call) {
|
|
854
|
+
pm_node_destroy(&parser, root);
|
|
855
|
+
pm_parser_free(&parser);
|
|
856
|
+
return NULL;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
AST_ERB_CONTENT_NODE_T content_view = {
|
|
860
|
+
.base = block_node->base,
|
|
861
|
+
.tag_opening = block_node->tag_opening,
|
|
862
|
+
.content = block_node->content,
|
|
863
|
+
.tag_closing = block_node->tag_closing,
|
|
864
|
+
.analyzed_ruby = NULL,
|
|
865
|
+
.parsed = true,
|
|
866
|
+
.valid = true,
|
|
867
|
+
.prism_node = block_node->prism_node,
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
size_t erb_content_offset = 0;
|
|
871
|
+
|
|
872
|
+
if (context->source && block_node->content) {
|
|
873
|
+
erb_content_offset = calculate_byte_offset_from_pos(context->source, block_node->content->location.start);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
const uint8_t* erb_content_source = (const uint8_t*) parser.start;
|
|
877
|
+
|
|
878
|
+
render_block_fields_T block_fields = {
|
|
879
|
+
.block_body = block_node->body,
|
|
880
|
+
.block_arguments = block_node->block_arguments,
|
|
881
|
+
.rescue_clause = block_node->rescue_clause,
|
|
882
|
+
.else_clause = block_node->else_clause,
|
|
883
|
+
.ensure_clause = block_node->ensure_clause,
|
|
884
|
+
.end_node = block_node->end_node,
|
|
885
|
+
};
|
|
886
|
+
|
|
887
|
+
AST_ERB_RENDER_NODE_T* render_node = create_render_node_from_call(
|
|
888
|
+
&content_view,
|
|
889
|
+
render_call,
|
|
890
|
+
&parser,
|
|
891
|
+
context->source,
|
|
892
|
+
erb_content_offset,
|
|
893
|
+
erb_content_source,
|
|
894
|
+
&block_fields,
|
|
895
|
+
context->allocator
|
|
896
|
+
);
|
|
897
|
+
|
|
898
|
+
pm_node_destroy(&parser, root);
|
|
899
|
+
pm_parser_free(&parser);
|
|
900
|
+
|
|
901
|
+
return render_node;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
static void transform_render_nodes_in_array(hb_array_T* array, analyze_ruby_context_T* context) {
|
|
905
|
+
if (!array) { return; }
|
|
906
|
+
|
|
907
|
+
for (size_t index = 0; index < hb_array_size(array); index++) {
|
|
908
|
+
AST_NODE_T* child = hb_array_get(array, index);
|
|
909
|
+
if (!child) { continue; }
|
|
910
|
+
|
|
911
|
+
AST_ERB_RENDER_NODE_T* render_node = NULL;
|
|
912
|
+
|
|
913
|
+
if (child->type == AST_ERB_CONTENT_NODE) {
|
|
914
|
+
render_node = try_transform_content_node((AST_ERB_CONTENT_NODE_T*) child, context);
|
|
915
|
+
} else if (child->type == AST_ERB_BLOCK_NODE) {
|
|
916
|
+
render_node = try_transform_block_node((AST_ERB_BLOCK_NODE_T*) child, context);
|
|
917
|
+
}
|
|
722
918
|
|
|
723
919
|
if (render_node) { hb_array_set(array, index, render_node); }
|
|
724
920
|
}
|