herb 0.9.4-arm-linux-gnu → 0.9.5-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.
@@ -2,8 +2,14 @@
2
2
  #include <stdbool.h>
3
3
  #include <string.h>
4
4
 
5
+ #include "../include/analyze/action_view/tag_helper_node_builders.h"
6
+ #include "../include/analyze/action_view/tag_helpers.h"
5
7
  #include "../include/analyze/analyzed_ruby.h"
8
+ #include "../include/analyze/helpers.h"
9
+ #include "../include/ast/ast_nodes.h"
10
+ #include "../include/lib/hb_array.h"
6
11
  #include "../include/lib/string.h"
12
+ #include "../include/prism/prism_helpers.h"
7
13
 
8
14
  bool has_if_node(analyzed_ruby_T* analyzed) {
9
15
  return analyzed && analyzed->if_node_count > 0;
@@ -526,3 +532,403 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) {
526
532
 
527
533
  return false;
528
534
  }
535
+
536
+ static pm_block_node_t* find_first_block_node(pm_node_t* node) {
537
+ if (!node) { return NULL; }
538
+
539
+ if (node->type == PM_CALL_NODE) {
540
+ pm_call_node_t* call = (pm_call_node_t*) node;
541
+
542
+ if (call->block && call->block->type == PM_BLOCK_NODE) { return (pm_block_node_t*) call->block; }
543
+ }
544
+
545
+ if (node->type == PM_PROGRAM_NODE) {
546
+ pm_program_node_t* program = (pm_program_node_t*) node;
547
+
548
+ if (program->statements && program->statements->body.size > 0) {
549
+ return find_first_block_node(program->statements->body.nodes[0]);
550
+ }
551
+ }
552
+
553
+ if (node->type == PM_STATEMENTS_NODE) {
554
+ pm_statements_node_t* statements = (pm_statements_node_t*) node;
555
+
556
+ if (statements->body.size > 0) { return find_first_block_node(statements->body.nodes[0]); }
557
+ }
558
+
559
+ return NULL;
560
+ }
561
+
562
+ static position_T prism_to_source_position(
563
+ const uint8_t* prism_pointer,
564
+ const uint8_t* prism_source_start,
565
+ size_t source_base_offset,
566
+ const char* source
567
+ ) {
568
+ if (!source || !prism_source_start) { return (position_T) { .line = 1, .column = 0 }; }
569
+
570
+ size_t prism_offset = (size_t) (prism_pointer - prism_source_start);
571
+ return byte_offset_to_position(source, source_base_offset + prism_offset);
572
+ }
573
+
574
+ static token_T* create_parameter_name_token(
575
+ pm_location_t location,
576
+ const char* name,
577
+ const uint8_t* prism_source_start,
578
+ size_t source_base_offset,
579
+ const char* source,
580
+ hb_allocator_T* allocator
581
+ ) {
582
+ position_T start = prism_to_source_position(location.start, prism_source_start, source_base_offset, source);
583
+ position_T end = prism_to_source_position(location.end, prism_source_start, source_base_offset, source);
584
+
585
+ return create_synthetic_token(allocator, name, TOKEN_IDENTIFIER, start, end);
586
+ }
587
+
588
+ static void append_parameter(
589
+ hb_array_T* result,
590
+ token_T* name_token,
591
+ AST_RUBY_LITERAL_NODE_T* default_value,
592
+ const char* kind,
593
+ bool required,
594
+ position_T start,
595
+ position_T end,
596
+ hb_allocator_T* allocator
597
+ ) {
598
+ hb_array_append(
599
+ result,
600
+ ast_ruby_parameter_node_init(
601
+ name_token,
602
+ default_value,
603
+ hb_string(kind),
604
+ required,
605
+ start,
606
+ end,
607
+ hb_array_init(0, allocator),
608
+ allocator
609
+ )
610
+ );
611
+ }
612
+
613
+ hb_array_T* extract_parameters_from_prism(
614
+ pm_parameters_node_t* parameters,
615
+ pm_parser_t* parser,
616
+ const char* source,
617
+ size_t source_base_offset,
618
+ const uint8_t* prism_source_start,
619
+ hb_allocator_T* allocator
620
+ ) {
621
+ if (!parameters) { return hb_array_init(0, allocator); }
622
+
623
+ size_t count = parameters->requireds.size + parameters->optionals.size + parameters->keywords.size;
624
+ if (parameters->rest) { count++; }
625
+ if (parameters->keyword_rest) { count++; }
626
+ if (parameters->block) { count++; }
627
+
628
+ hb_array_T* result = hb_array_init(count, allocator);
629
+
630
+ // Required positional: |item|
631
+ for (size_t index = 0; index < parameters->requireds.size; index++) {
632
+ pm_node_t* node = parameters->requireds.nodes[index];
633
+ if (node->type != PM_REQUIRED_PARAMETER_NODE) { continue; }
634
+
635
+ pm_required_parameter_node_t* required = (pm_required_parameter_node_t*) node;
636
+ pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, required->name);
637
+ if (!constant) { continue; }
638
+
639
+ char* name = hb_allocator_strndup(allocator, (const char*) constant->start, constant->length);
640
+ position_T start = prism_to_source_position(node->location.start, prism_source_start, source_base_offset, source);
641
+ position_T end = prism_to_source_position(node->location.end, prism_source_start, source_base_offset, source);
642
+
643
+ append_parameter(
644
+ result,
645
+ create_parameter_name_token(node->location, name, prism_source_start, source_base_offset, source, allocator),
646
+ NULL,
647
+ "positional",
648
+ true,
649
+ start,
650
+ end,
651
+ allocator
652
+ );
653
+
654
+ hb_allocator_dealloc(allocator, name);
655
+ }
656
+
657
+ // Optional positional: |item = nil|
658
+ for (size_t index = 0; index < parameters->optionals.size; index++) {
659
+ pm_node_t* node = parameters->optionals.nodes[index];
660
+ if (node->type != PM_OPTIONAL_PARAMETER_NODE) { continue; }
661
+
662
+ pm_optional_parameter_node_t* optional = (pm_optional_parameter_node_t*) node;
663
+ size_t name_length = (size_t) (optional->name_loc.end - optional->name_loc.start);
664
+ char* name = hb_allocator_strndup(allocator, (const char*) optional->name_loc.start, name_length);
665
+
666
+ position_T start = prism_to_source_position(node->location.start, prism_source_start, source_base_offset, source);
667
+ position_T end = prism_to_source_position(node->location.end, prism_source_start, source_base_offset, source);
668
+
669
+ AST_RUBY_LITERAL_NODE_T* default_value = NULL;
670
+
671
+ if (optional->value) {
672
+ size_t value_length = (size_t) (optional->value->location.end - optional->value->location.start);
673
+ char* value_string = hb_allocator_strndup(allocator, (const char*) optional->value->location.start, value_length);
674
+ position_T value_start =
675
+ prism_to_source_position(optional->value->location.start, prism_source_start, source_base_offset, source);
676
+ position_T value_end =
677
+ prism_to_source_position(optional->value->location.end, prism_source_start, source_base_offset, source);
678
+
679
+ default_value = ast_ruby_literal_node_init(
680
+ hb_string_from_c_string(value_string),
681
+ value_start,
682
+ value_end,
683
+ hb_array_init(0, allocator),
684
+ allocator
685
+ );
686
+ hb_allocator_dealloc(allocator, value_string);
687
+ }
688
+
689
+ append_parameter(
690
+ result,
691
+ create_parameter_name_token(optional->name_loc, name, prism_source_start, source_base_offset, source, allocator),
692
+ default_value,
693
+ "positional",
694
+ false,
695
+ start,
696
+ end,
697
+ allocator
698
+ );
699
+
700
+ hb_allocator_dealloc(allocator, name);
701
+ }
702
+
703
+ // Rest: |*items|
704
+ if (parameters->rest && parameters->rest->type == PM_REST_PARAMETER_NODE) {
705
+ pm_rest_parameter_node_t* rest = (pm_rest_parameter_node_t*) parameters->rest;
706
+
707
+ if (rest->name) {
708
+ size_t name_length = (size_t) (rest->name_loc.end - rest->name_loc.start);
709
+ char* name = hb_allocator_strndup(allocator, (const char*) rest->name_loc.start, name_length);
710
+
711
+ position_T start =
712
+ prism_to_source_position(parameters->rest->location.start, prism_source_start, source_base_offset, source);
713
+ position_T end =
714
+ prism_to_source_position(parameters->rest->location.end, prism_source_start, source_base_offset, source);
715
+
716
+ append_parameter(
717
+ result,
718
+ create_parameter_name_token(rest->name_loc, name, prism_source_start, source_base_offset, source, allocator),
719
+ NULL,
720
+ "rest",
721
+ false,
722
+ start,
723
+ end,
724
+ allocator
725
+ );
726
+
727
+ hb_allocator_dealloc(allocator, name);
728
+ }
729
+ }
730
+
731
+ // Keywords: |name:| or |title: "default"|
732
+ for (size_t index = 0; index < parameters->keywords.size; index++) {
733
+ pm_node_t* keyword = parameters->keywords.nodes[index];
734
+
735
+ pm_location_t name_location;
736
+ bool is_required = false;
737
+ AST_RUBY_LITERAL_NODE_T* default_value = NULL;
738
+
739
+ if (keyword->type == PM_REQUIRED_KEYWORD_PARAMETER_NODE) {
740
+ name_location = ((pm_required_keyword_parameter_node_t*) keyword)->name_loc;
741
+ is_required = true;
742
+ } else if (keyword->type == PM_OPTIONAL_KEYWORD_PARAMETER_NODE) {
743
+ pm_optional_keyword_parameter_node_t* optional_keyword = (pm_optional_keyword_parameter_node_t*) keyword;
744
+ name_location = optional_keyword->name_loc;
745
+
746
+ if (optional_keyword->value) {
747
+ size_t value_length =
748
+ (size_t) (optional_keyword->value->location.end - optional_keyword->value->location.start);
749
+ char* value_string =
750
+ hb_allocator_strndup(allocator, (const char*) optional_keyword->value->location.start, value_length);
751
+
752
+ position_T value_start = prism_to_source_position(
753
+ optional_keyword->value->location.start,
754
+ prism_source_start,
755
+ source_base_offset,
756
+ source
757
+ );
758
+
759
+ position_T value_end = prism_to_source_position(
760
+ optional_keyword->value->location.end,
761
+ prism_source_start,
762
+ source_base_offset,
763
+ source
764
+ );
765
+
766
+ default_value = ast_ruby_literal_node_init(
767
+ hb_string_from_c_string(value_string),
768
+ value_start,
769
+ value_end,
770
+ hb_array_init(0, allocator),
771
+ allocator
772
+ );
773
+
774
+ hb_allocator_dealloc(allocator, value_string);
775
+ }
776
+ } else {
777
+ continue;
778
+ }
779
+
780
+ size_t name_length = (size_t) (name_location.end - name_location.start);
781
+ if (name_length > 0 && name_location.start[name_length - 1] == ':') { name_length--; }
782
+ char* name = hb_allocator_strndup(allocator, (const char*) name_location.start, name_length);
783
+
784
+ position_T start =
785
+ prism_to_source_position(keyword->location.start, prism_source_start, source_base_offset, source);
786
+ position_T end = prism_to_source_position(keyword->location.end, prism_source_start, source_base_offset, source);
787
+
788
+ append_parameter(
789
+ result,
790
+ create_parameter_name_token(name_location, name, prism_source_start, source_base_offset, source, allocator),
791
+ default_value,
792
+ "keyword",
793
+ is_required,
794
+ start,
795
+ end,
796
+ allocator
797
+ );
798
+
799
+ hb_allocator_dealloc(allocator, name);
800
+ }
801
+
802
+ // Keyword rest: |**opts| or |**|
803
+ if (parameters->keyword_rest && parameters->keyword_rest->type == PM_KEYWORD_REST_PARAMETER_NODE) {
804
+ pm_keyword_rest_parameter_node_t* keyword_rest = (pm_keyword_rest_parameter_node_t*) parameters->keyword_rest;
805
+
806
+ position_T start = prism_to_source_position(
807
+ parameters->keyword_rest->location.start,
808
+ prism_source_start,
809
+ source_base_offset,
810
+ source
811
+ );
812
+
813
+ position_T end =
814
+ prism_to_source_position(parameters->keyword_rest->location.end, prism_source_start, source_base_offset, source);
815
+
816
+ if (keyword_rest->name) {
817
+ size_t name_length = (size_t) (keyword_rest->name_loc.end - keyword_rest->name_loc.start);
818
+ char* name = hb_allocator_strndup(allocator, (const char*) keyword_rest->name_loc.start, name_length);
819
+
820
+ append_parameter(
821
+ result,
822
+ create_parameter_name_token(
823
+ keyword_rest->name_loc,
824
+ name,
825
+ prism_source_start,
826
+ source_base_offset,
827
+ source,
828
+ allocator
829
+ ),
830
+ NULL,
831
+ "keyword_rest",
832
+ false,
833
+ start,
834
+ end,
835
+ allocator
836
+ );
837
+
838
+ hb_allocator_dealloc(allocator, name);
839
+ } else {
840
+ // Anonymous **
841
+ append_parameter(result, NULL, NULL, "keyword_rest", false, start, end, allocator);
842
+ }
843
+ }
844
+
845
+ // Block: |&blk|
846
+ if (parameters->block) {
847
+ pm_block_parameter_node_t* block_param = parameters->block;
848
+
849
+ if (block_param->name) {
850
+ size_t name_length = (size_t) (block_param->name_loc.end - block_param->name_loc.start);
851
+ char* name = hb_allocator_strndup(allocator, (const char*) block_param->name_loc.start, name_length);
852
+
853
+ position_T start =
854
+ prism_to_source_position(block_param->base.location.start, prism_source_start, source_base_offset, source);
855
+ position_T end =
856
+ prism_to_source_position(block_param->base.location.end, prism_source_start, source_base_offset, source);
857
+
858
+ append_parameter(
859
+ result,
860
+ create_parameter_name_token(
861
+ block_param->name_loc,
862
+ name,
863
+ prism_source_start,
864
+ source_base_offset,
865
+ source,
866
+ allocator
867
+ ),
868
+ NULL,
869
+ "block",
870
+ false,
871
+ start,
872
+ end,
873
+ allocator
874
+ );
875
+
876
+ hb_allocator_dealloc(allocator, name);
877
+ }
878
+ }
879
+
880
+ return result;
881
+ }
882
+
883
+ hb_array_T* extract_block_arguments_from_erb_node(
884
+ const AST_ERB_CONTENT_NODE_T* erb_node,
885
+ const char* source,
886
+ hb_array_T* errors,
887
+ hb_allocator_T* allocator
888
+ ) {
889
+ if (!erb_node || !erb_node->analyzed_ruby || !erb_node->analyzed_ruby->parsed) { return hb_array_init(0, allocator); }
890
+
891
+ pm_parser_t* parser = &erb_node->analyzed_ruby->parser;
892
+ pm_block_node_t* block_node = find_first_block_node(erb_node->analyzed_ruby->root);
893
+
894
+ if (!block_node || !block_node->parameters) { return hb_array_init(0, allocator); }
895
+ if (block_node->parameters->type != PM_BLOCK_PARAMETERS_NODE) { return hb_array_init(0, allocator); }
896
+
897
+ pm_block_parameters_node_t* block_parameters = (pm_block_parameters_node_t*) block_node->parameters;
898
+ size_t erb_content_offset = 0;
899
+
900
+ if (source && erb_node->content) {
901
+ erb_content_offset = calculate_byte_offset_from_position(source, erb_node->content->location.start);
902
+ }
903
+
904
+ const uint8_t* prism_source_start = (const uint8_t*) parser->start;
905
+
906
+ if (errors) {
907
+ for (const pm_diagnostic_t* error = (const pm_diagnostic_t*) parser->error_list.head; error != NULL;
908
+ error = (const pm_diagnostic_t*) error->node.next) {
909
+ if (error->diag_id == PM_ERR_BLOCK_TERM_END) { continue; }
910
+ if (error->diag_id == PM_ERR_BLOCK_TERM_BRACE) { continue; }
911
+ if (error->diag_id == PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT) { continue; }
912
+
913
+ size_t error_start_offset = (size_t) (error->location.start - prism_source_start);
914
+ size_t error_end_offset = (size_t) (error->location.end - prism_source_start);
915
+
916
+ position_T error_start = byte_offset_to_position(source, erb_content_offset + error_start_offset);
917
+ position_T error_end = byte_offset_to_position(source, erb_content_offset + error_end_offset);
918
+
919
+ RUBY_PARSE_ERROR_T* parse_error =
920
+ ruby_parse_error_from_prism_error_with_positions(error, error_start, error_end, allocator);
921
+
922
+ hb_array_append(errors, parse_error);
923
+ }
924
+ }
925
+
926
+ return extract_parameters_from_prism(
927
+ block_parameters->parameters,
928
+ parser,
929
+ source,
930
+ erb_content_offset,
931
+ prism_source_start,
932
+ allocator
933
+ );
934
+ }
@@ -322,6 +322,7 @@ static AST_NODE_T* build_block_node(control_builder_context_T* context) {
322
322
  context->tag_closing,
323
323
  HERB_PRISM_NODE_EMPTY,
324
324
  context->children,
325
+ hb_array_init(0, context->allocator),
325
326
  NULL,
326
327
  NULL,
327
328
  NULL,
@@ -153,6 +153,22 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node, hb_allocator_T* allo
153
153
  break;
154
154
  }
155
155
 
156
+ case AST_ERB_RENDER_NODE: {
157
+ const AST_ERB_RENDER_NODE_T* erb_render_node = (const AST_ERB_RENDER_NODE_T*) node;
158
+
159
+ if (erb_render_node->end_node == NULL) {
160
+ append_missing_erb_end_tag_error(
161
+ hb_string("`<" "%" " render " "%" ">`"),
162
+ erb_render_node->tag_opening->location.start,
163
+ erb_render_node->tag_closing->location.end,
164
+ allocator,
165
+ node->errors
166
+ );
167
+ }
168
+
169
+ break;
170
+ }
171
+
156
172
  default: break;
157
173
  }
158
174
  }
@@ -5,6 +5,7 @@
5
5
  #include "../include/extract.h"
6
6
  #include "../include/lib/hb_allocator.h"
7
7
  #include "../include/lib/hb_string.h"
8
+ #include "../include/lib/string.h"
8
9
  #include "../include/prism/prism_helpers.h"
9
10
 
10
11
  #include <prism.h>
@@ -22,8 +23,8 @@ static bool document_has_anonymous_keyword_rest(AST_DOCUMENT_NODE_T* document) {
22
23
  if (!strict_locals_node->locals) { continue; }
23
24
 
24
25
  for (size_t local_index = 0; local_index < hb_array_size(strict_locals_node->locals); local_index++) {
25
- AST_RUBY_STRICT_LOCAL_NODE_T* local = hb_array_get(strict_locals_node->locals, local_index);
26
- if (local && local->double_splat && local->name == NULL) { return true; }
26
+ AST_RUBY_PARAMETER_NODE_T* local = hb_array_get(strict_locals_node->locals, local_index);
27
+ if (local && string_equals(local->kind.data, "keyword_rest") && local->name == NULL) { return true; }
27
28
  }
28
29
  }
29
30