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.
@@ -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
- AST_ERB_RENDER_NODE_T* render_node = ast_erb_render_node_init(
630
- erb_node->tag_opening,
631
- erb_node->content,
632
- erb_node->tag_closing,
633
- erb_node->analyzed_ruby,
634
- prism_node,
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 void transform_render_nodes_in_array(hb_array_T* array, analyze_ruby_context_T* context) {
686
- if (!array) { return; }
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
- for (size_t index = 0; index < hb_array_size(array); index++) {
689
- AST_NODE_T* child = hb_array_get(array, index);
690
- if (!child || child->type != AST_ERB_CONTENT_NODE) { continue; }
804
+ const char* opening_string = tag_opening->value.data;
805
+ return opening_string && strstr(opening_string, "#") != NULL;
806
+ }
691
807
 
692
- AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*) child;
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
- if (!erb_node->analyzed_ruby || !erb_node->analyzed_ruby->valid || !erb_node->analyzed_ruby->parsed) { continue; }
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
- token_T* tag_opening = erb_node->tag_opening;
818
+ size_t erb_content_offset = 0;
697
819
 
698
- if (tag_opening && !hb_string_is_empty(tag_opening->value)) {
699
- const char* opening_string = tag_opening->value.data;
700
- if (opening_string && strstr(opening_string, "#") != NULL) { continue; }
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
- pm_call_node_t* render_call = find_render_call(erb_node->analyzed_ruby->root, &erb_node->analyzed_ruby->parser);
704
- if (!render_call) { continue; }
824
+ const uint8_t* erb_content_source = (const uint8_t*) erb_node->analyzed_ruby->parser.start;
705
825
 
706
- size_t erb_content_offset = 0;
707
- if (context->source && erb_node->content) {
708
- erb_content_offset = calculate_byte_offset_from_pos(context->source, erb_node->content->location.start);
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
- const uint8_t* erb_content_source = (const uint8_t*) erb_node->analyzed_ruby->parser.start;
844
+ const char* ruby_source = block_node->content->value.data;
845
+ size_t ruby_length = block_node->content->value.length;
712
846
 
713
- AST_ERB_RENDER_NODE_T* render_node = create_render_node_from_call(
714
- erb_node,
715
- render_call,
716
- &erb_node->analyzed_ruby->parser,
717
- context->source,
718
- erb_content_offset,
719
- erb_content_source,
720
- context->allocator
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
  }