herb 0.9.2-arm-linux-gnu → 0.9.4-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/README.md +2 -0
- data/config.yml +125 -0
- data/ext/herb/error_helpers.c +172 -2
- data/ext/herb/extconf.rb +6 -0
- data/ext/herb/extension.c +16 -2
- data/ext/herb/extension_helpers.c +6 -5
- data/ext/herb/extension_helpers.h +4 -4
- data/ext/herb/nodes.c +89 -3
- 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/erb_content_node.rb +32 -0
- data/lib/herb/ast/nodes.rb +244 -3
- data/lib/herb/cli.rb +12 -2
- data/lib/herb/engine/compiler.rb +166 -75
- data/lib/herb/engine/validators/security_validator.rb +40 -0
- data/lib/herb/engine.rb +3 -0
- data/lib/herb/errors.rb +268 -0
- data/lib/herb/parser_options.rb +7 -2
- data/lib/herb/project.rb +58 -17
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +82 -0
- data/lib/herb.rb +1 -0
- data/sig/herb/ast/erb_content_node.rbs +13 -0
- data/sig/herb/ast/nodes.rbs +98 -2
- data/sig/herb/engine/compiler.rbs +31 -2
- data/sig/herb/engine/validators/security_validator.rbs +4 -0
- data/sig/herb/engine.rbs +3 -0
- data/sig/herb/errors.rbs +122 -0
- data/sig/herb/parser_options.rbs +6 -2
- data/sig/herb/visitor.rbs +12 -0
- data/sig/serialized_ast_errors.rbs +29 -0
- data/sig/serialized_ast_nodes.rbs +19 -0
- data/src/analyze/action_view/attribute_extraction_helpers.c +420 -91
- data/src/analyze/action_view/image_tag.c +87 -0
- data/src/analyze/action_view/javascript_include_tag.c +22 -12
- data/src/analyze/action_view/registry.c +6 -3
- data/src/analyze/action_view/tag.c +19 -2
- data/src/analyze/action_view/tag_helper_node_builders.c +105 -36
- data/src/analyze/action_view/tag_helpers.c +792 -44
- data/src/analyze/analyze.c +167 -13
- data/src/analyze/{helpers.c → analyze_helpers.c} +1 -1
- data/src/analyze/analyzed_ruby.c +1 -1
- data/src/analyze/builders.c +11 -8
- data/src/analyze/conditional_elements.c +6 -7
- data/src/analyze/conditional_open_tags.c +6 -7
- data/src/analyze/control_type.c +4 -2
- data/src/analyze/invalid_structures.c +5 -5
- data/src/analyze/missing_end.c +2 -2
- data/src/analyze/parse_errors.c +47 -6
- data/src/analyze/prism_annotate.c +7 -7
- data/src/analyze/render_nodes.c +6 -26
- data/src/analyze/strict_locals.c +651 -0
- data/src/analyze/transform.c +7 -0
- data/src/{ast_node.c → ast/ast_node.c} +8 -8
- data/src/{ast_nodes.c → ast/ast_nodes.c} +82 -11
- data/src/{ast_pretty_print.c → ast/ast_pretty_print.c} +113 -9
- data/src/{pretty_print.c → ast/pretty_print.c} +9 -9
- data/src/errors.c +398 -8
- data/src/extract.c +5 -5
- data/src/herb.c +15 -5
- data/src/include/analyze/action_view/attribute_extraction_helpers.h +3 -1
- data/src/include/analyze/action_view/tag_helper_handler.h +3 -3
- data/src/include/analyze/action_view/tag_helper_node_builders.h +34 -5
- data/src/include/analyze/action_view/tag_helpers.h +4 -3
- data/src/include/analyze/analyze.h +12 -5
- data/src/include/analyze/analyzed_ruby.h +2 -2
- data/src/include/analyze/builders.h +4 -4
- data/src/include/analyze/conditional_elements.h +2 -2
- data/src/include/analyze/conditional_open_tags.h +2 -2
- data/src/include/analyze/control_type.h +1 -1
- data/src/include/analyze/helpers.h +2 -2
- data/src/include/analyze/invalid_structures.h +1 -1
- data/src/include/analyze/prism_annotate.h +2 -2
- data/src/include/analyze/render_nodes.h +1 -1
- data/src/include/analyze/strict_locals.h +11 -0
- data/src/include/{ast_node.h → ast/ast_node.h} +4 -4
- data/src/include/{ast_nodes.h → ast/ast_nodes.h} +38 -14
- data/src/include/{ast_pretty_print.h → ast/ast_pretty_print.h} +3 -3
- data/src/include/{pretty_print.h → ast/pretty_print.h} +4 -4
- data/src/include/errors.h +65 -7
- data/src/include/extract.h +2 -2
- data/src/include/herb.h +5 -5
- data/src/include/{lex_helpers.h → lexer/lex_helpers.h} +5 -5
- data/src/include/{lexer.h → lexer/lexer.h} +1 -1
- data/src/include/{lexer_peek_helpers.h → lexer/lexer_peek_helpers.h} +2 -2
- data/src/include/{lexer_struct.h → lexer/lexer_struct.h} +2 -2
- data/src/include/{token.h → lexer/token.h} +3 -3
- data/src/include/{token_matchers.h → lexer/token_matchers.h} +1 -1
- data/src/include/{token_struct.h → lexer/token_struct.h} +3 -3
- data/src/include/{util → lib}/hb_foreach.h +1 -1
- data/src/include/{util → lib}/hb_string.h +5 -1
- data/src/include/{location.h → location/location.h} +1 -1
- data/src/include/parser/dot_notation.h +12 -0
- data/src/include/{parser.h → parser/parser.h} +11 -4
- data/src/include/{parser_helpers.h → parser/parser_helpers.h} +6 -6
- data/src/include/{prism_context.h → prism/prism_context.h} +2 -2
- data/src/include/{prism_helpers.h → prism/prism_helpers.h} +6 -6
- data/src/include/{html_util.h → util/html_util.h} +1 -1
- data/src/include/util/ruby_util.h +9 -0
- data/src/include/{utf8.h → util/utf8.h} +1 -1
- data/src/include/{util.h → util/util.h} +1 -1
- data/src/include/version.h +1 -1
- data/src/include/visitor.h +3 -3
- data/src/{lexer_peek_helpers.c → lexer/lexer_peek_helpers.c} +3 -3
- data/src/{token.c → lexer/token.c} +8 -8
- data/src/{token_matchers.c → lexer/token_matchers.c} +2 -2
- data/src/lexer.c +6 -6
- data/src/{util → lib}/hb_allocator.c +2 -2
- data/src/{util → lib}/hb_arena.c +1 -1
- data/src/{util → lib}/hb_arena_debug.c +2 -2
- data/src/{util → lib}/hb_array.c +2 -2
- data/src/{util → lib}/hb_buffer.c +2 -2
- data/src/{util → lib}/hb_narray.c +1 -1
- data/src/{util → lib}/hb_string.c +2 -2
- data/src/{location.c → location/location.c} +2 -2
- data/src/{position.c → location/position.c} +2 -2
- data/src/{range.c → location/range.c} +1 -1
- data/src/main.c +11 -11
- data/src/parser/dot_notation.c +100 -0
- data/src/{parser_match_tags.c → parser/match_tags.c} +34 -5
- data/src/{parser_helpers.c → parser/parser_helpers.c} +10 -10
- data/src/parser.c +68 -32
- data/src/{prism_helpers.c → prism/prism_helpers.c} +7 -7
- data/src/{ruby_parser.c → prism/ruby_parser.c} +1 -1
- data/src/{html_util.c → util/html_util.c} +4 -4
- data/src/{io.c → util/io.c} +3 -3
- data/src/util/ruby_util.c +42 -0
- data/src/{utf8.c → util/utf8.c} +2 -2
- data/src/{util.c → util/util.c} +4 -4
- data/src/visitor.c +35 -3
- data/templates/ext/herb/error_helpers.c.erb +2 -2
- data/templates/ext/herb/nodes.c.erb +1 -1
- data/templates/java/error_helpers.c.erb +1 -1
- data/templates/java/error_helpers.h.erb +2 -2
- data/templates/java/nodes.c.erb +4 -4
- data/templates/java/nodes.h.erb +1 -1
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +4 -4
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +4 -4
- data/templates/lib/herb/visitor.rb.erb +14 -0
- data/templates/src/analyze/missing_end.c.erb +2 -2
- data/templates/src/{ast_nodes.c.erb → ast/ast_nodes.c.erb} +9 -9
- data/templates/src/{ast_pretty_print.c.erb → ast/ast_pretty_print.c.erb} +8 -8
- data/templates/src/errors.c.erb +8 -8
- data/templates/src/include/{ast_nodes.h.erb → ast/ast_nodes.h.erb} +11 -12
- data/templates/src/include/{ast_pretty_print.h.erb → ast/ast_pretty_print.h.erb} +2 -2
- data/templates/src/include/errors.h.erb +7 -7
- data/templates/src/{parser_match_tags.c.erb → parser/match_tags.c.erb} +4 -4
- data/templates/src/visitor.c.erb +3 -3
- data/templates/wasm/error_helpers.cpp.erb +4 -4
- data/templates/wasm/nodes.cpp.erb +5 -5
- metadata +76 -68
- data/src/include/element_source.h +0 -10
- /data/src/include/{util → lib}/hb_allocator.h +0 -0
- /data/src/include/{util → lib}/hb_arena.h +0 -0
- /data/src/include/{util → lib}/hb_arena_debug.h +0 -0
- /data/src/include/{util → lib}/hb_array.h +0 -0
- /data/src/include/{util → lib}/hb_buffer.h +0 -0
- /data/src/include/{util → lib}/hb_narray.h +0 -0
- /data/src/include/{util → lib}/string.h +0 -0
- /data/src/include/{position.h → location/position.h} +0 -0
- /data/src/include/{range.h → location/range.h} +0 -0
- /data/src/include/{herb_prism_node.h → prism/herb_prism_node.h} +0 -0
- /data/src/include/{prism_serialized.h → prism/prism_serialized.h} +0 -0
- /data/src/include/{ruby_parser.h → prism/ruby_parser.h} +0 -0
- /data/src/include/{io.h → util/io.h} +0 -0
- /data/templates/src/include/{util → lib}/hb_foreach.h.erb +0 -0
data/src/analyze/analyze.c
CHANGED
|
@@ -9,16 +9,17 @@
|
|
|
9
9
|
#include "../include/analyze/helpers.h"
|
|
10
10
|
#include "../include/analyze/invalid_structures.h"
|
|
11
11
|
#include "../include/analyze/render_nodes.h"
|
|
12
|
-
#include "../include/
|
|
13
|
-
#include "../include/
|
|
12
|
+
#include "../include/analyze/strict_locals.h"
|
|
13
|
+
#include "../include/ast/ast_node.h"
|
|
14
|
+
#include "../include/ast/ast_nodes.h"
|
|
14
15
|
#include "../include/errors.h"
|
|
15
|
-
#include "../include/
|
|
16
|
-
#include "../include/
|
|
17
|
-
#include "../include/
|
|
18
|
-
#include "../include/
|
|
19
|
-
#include "../include/
|
|
20
|
-
#include "../include/
|
|
21
|
-
#include "../include/
|
|
16
|
+
#include "../include/lexer/token_struct.h"
|
|
17
|
+
#include "../include/lib/hb_array.h"
|
|
18
|
+
#include "../include/lib/hb_string.h"
|
|
19
|
+
#include "../include/lib/string.h"
|
|
20
|
+
#include "../include/location/location.h"
|
|
21
|
+
#include "../include/location/position.h"
|
|
22
|
+
#include "../include/parser/parser.h"
|
|
22
23
|
#include "../include/visitor.h"
|
|
23
24
|
|
|
24
25
|
#include <prism.h>
|
|
@@ -74,8 +75,7 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) {
|
|
|
74
75
|
|
|
75
76
|
hb_string_T opening = erb_content_node->tag_opening->value;
|
|
76
77
|
|
|
77
|
-
if (!hb_string_equals(opening, hb_string("
|
|
78
|
-
&& !hb_string_equals(opening, hb_string("<%#")) && !hb_string_equals(opening, hb_string("<%graphql"))) {
|
|
78
|
+
if (!hb_string_equals(opening, hb_string("<%#")) && !hb_string_equals(opening, hb_string("<%graphql"))) {
|
|
79
79
|
analyzed_ruby_T* analyzed = herb_analyze_ruby(erb_content_node->content->value);
|
|
80
80
|
|
|
81
81
|
erb_content_node->parsed = true;
|
|
@@ -252,6 +252,14 @@ static size_t process_begin_structure(
|
|
|
252
252
|
analyze_ruby_context_T* context
|
|
253
253
|
);
|
|
254
254
|
|
|
255
|
+
static size_t process_block_structure(
|
|
256
|
+
AST_NODE_T* node,
|
|
257
|
+
hb_array_T* array,
|
|
258
|
+
size_t index,
|
|
259
|
+
hb_array_T* output_array,
|
|
260
|
+
analyze_ruby_context_T* context
|
|
261
|
+
);
|
|
262
|
+
|
|
255
263
|
static size_t process_generic_structure(
|
|
256
264
|
AST_NODE_T* node,
|
|
257
265
|
hb_array_T* array,
|
|
@@ -272,8 +280,8 @@ static size_t process_control_structure(
|
|
|
272
280
|
switch (initial_type) {
|
|
273
281
|
case CONTROL_TYPE_CASE:
|
|
274
282
|
case CONTROL_TYPE_CASE_MATCH: return process_case_structure(node, array, index, output_array, context);
|
|
275
|
-
|
|
276
283
|
case CONTROL_TYPE_BEGIN: return process_begin_structure(node, array, index, output_array, context);
|
|
284
|
+
case CONTROL_TYPE_BLOCK: return process_block_structure(node, array, index, output_array, context);
|
|
277
285
|
|
|
278
286
|
default: return process_generic_structure(node, array, index, output_array, context, initial_type);
|
|
279
287
|
}
|
|
@@ -630,6 +638,126 @@ static size_t process_begin_structure(
|
|
|
630
638
|
return index;
|
|
631
639
|
}
|
|
632
640
|
|
|
641
|
+
static size_t process_block_structure(
|
|
642
|
+
AST_NODE_T* node,
|
|
643
|
+
hb_array_T* array,
|
|
644
|
+
size_t index,
|
|
645
|
+
hb_array_T* output_array,
|
|
646
|
+
analyze_ruby_context_T* context
|
|
647
|
+
) {
|
|
648
|
+
hb_allocator_T* allocator = context->allocator;
|
|
649
|
+
AST_ERB_CONTENT_NODE_T* erb_node = get_erb_content_at(array, index);
|
|
650
|
+
if (!erb_node) { return index; }
|
|
651
|
+
hb_array_T* children = hb_array_init(8, allocator);
|
|
652
|
+
|
|
653
|
+
index++;
|
|
654
|
+
index = process_block_children(node, array, index, children, context, CONTROL_TYPE_BLOCK);
|
|
655
|
+
|
|
656
|
+
AST_ERB_RESCUE_NODE_T* rescue_clause = NULL;
|
|
657
|
+
AST_ERB_ELSE_NODE_T* else_clause = NULL;
|
|
658
|
+
AST_ERB_ENSURE_NODE_T* ensure_clause = NULL;
|
|
659
|
+
|
|
660
|
+
control_type_t next_type = CONTROL_TYPE_UNKNOWN;
|
|
661
|
+
AST_ERB_CONTENT_NODE_T* next_erb = NULL;
|
|
662
|
+
|
|
663
|
+
if (peek_control_type(array, index, &next_type, &next_erb) && next_type == CONTROL_TYPE_RESCUE) {
|
|
664
|
+
AST_NODE_T* rescue_node = NULL;
|
|
665
|
+
index = process_subsequent_block(node, array, index, &rescue_node, context, CONTROL_TYPE_BLOCK);
|
|
666
|
+
rescue_clause = (AST_ERB_RESCUE_NODE_T*) rescue_node;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
if (peek_control_type(array, index, &next_type, &next_erb) && next_type == CONTROL_TYPE_ELSE) {
|
|
670
|
+
hb_array_T* else_children = hb_array_init(8, allocator);
|
|
671
|
+
index++;
|
|
672
|
+
|
|
673
|
+
index = process_block_children(node, array, index, else_children, context, CONTROL_TYPE_BLOCK);
|
|
674
|
+
|
|
675
|
+
hb_array_T* else_errors = next_erb->base.errors;
|
|
676
|
+
next_erb->base.errors = NULL;
|
|
677
|
+
|
|
678
|
+
else_clause = ast_erb_else_node_init(
|
|
679
|
+
next_erb->tag_opening,
|
|
680
|
+
next_erb->content,
|
|
681
|
+
next_erb->tag_closing,
|
|
682
|
+
else_children,
|
|
683
|
+
next_erb->tag_opening->location.start,
|
|
684
|
+
erb_content_end_position(next_erb),
|
|
685
|
+
else_errors,
|
|
686
|
+
allocator
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
ast_node_free((AST_NODE_T*) next_erb, allocator);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if (peek_control_type(array, index, &next_type, &next_erb) && next_type == CONTROL_TYPE_ENSURE) {
|
|
693
|
+
hb_array_T* ensure_children = hb_array_init(8, allocator);
|
|
694
|
+
index++;
|
|
695
|
+
|
|
696
|
+
const control_type_t ensure_stop[] = { CONTROL_TYPE_END, CONTROL_TYPE_BLOCK_CLOSE };
|
|
697
|
+
collect_children_until(array, &index, ensure_children, ensure_stop, sizeof(ensure_stop) / sizeof(ensure_stop[0]));
|
|
698
|
+
|
|
699
|
+
hb_array_T* ensure_errors = next_erb->base.errors;
|
|
700
|
+
next_erb->base.errors = NULL;
|
|
701
|
+
|
|
702
|
+
ensure_clause = ast_erb_ensure_node_init(
|
|
703
|
+
next_erb->tag_opening,
|
|
704
|
+
next_erb->content,
|
|
705
|
+
next_erb->tag_closing,
|
|
706
|
+
ensure_children,
|
|
707
|
+
next_erb->tag_opening->location.start,
|
|
708
|
+
erb_content_end_position(next_erb),
|
|
709
|
+
ensure_errors,
|
|
710
|
+
allocator
|
|
711
|
+
);
|
|
712
|
+
|
|
713
|
+
ast_node_free((AST_NODE_T*) next_erb, allocator);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
const control_type_t end_types[] = { CONTROL_TYPE_BLOCK_CLOSE, CONTROL_TYPE_END };
|
|
717
|
+
AST_ERB_END_NODE_T* end_node =
|
|
718
|
+
consume_end_node(array, &index, end_types, sizeof(end_types) / sizeof(end_types[0]), allocator);
|
|
719
|
+
|
|
720
|
+
position_T start_position = erb_node->tag_opening->location.start;
|
|
721
|
+
position_T end_position = erb_content_end_position(erb_node);
|
|
722
|
+
|
|
723
|
+
if (end_node) {
|
|
724
|
+
end_position = end_node->base.location.end;
|
|
725
|
+
} else if (ensure_clause) {
|
|
726
|
+
end_position = ensure_clause->base.location.end;
|
|
727
|
+
} else if (else_clause) {
|
|
728
|
+
end_position = else_clause->base.location.end;
|
|
729
|
+
} else if (rescue_clause) {
|
|
730
|
+
end_position = rescue_clause->base.location.end;
|
|
731
|
+
} else if (hb_array_size(children) > 0) {
|
|
732
|
+
AST_NODE_T* last_child = hb_array_last(children);
|
|
733
|
+
end_position = last_child->location.end;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
hb_array_T* block_errors = erb_node->base.errors;
|
|
737
|
+
erb_node->base.errors = NULL;
|
|
738
|
+
|
|
739
|
+
AST_ERB_BLOCK_NODE_T* block_node = ast_erb_block_node_init(
|
|
740
|
+
erb_node->tag_opening,
|
|
741
|
+
erb_node->content,
|
|
742
|
+
erb_node->tag_closing,
|
|
743
|
+
HERB_PRISM_NODE_EMPTY,
|
|
744
|
+
children,
|
|
745
|
+
rescue_clause,
|
|
746
|
+
else_clause,
|
|
747
|
+
ensure_clause,
|
|
748
|
+
end_node,
|
|
749
|
+
start_position,
|
|
750
|
+
end_position,
|
|
751
|
+
block_errors,
|
|
752
|
+
allocator
|
|
753
|
+
);
|
|
754
|
+
|
|
755
|
+
ast_node_free((AST_NODE_T*) erb_node, allocator);
|
|
756
|
+
hb_array_append(output_array, (AST_NODE_T*) block_node);
|
|
757
|
+
|
|
758
|
+
return index;
|
|
759
|
+
}
|
|
760
|
+
|
|
633
761
|
static size_t process_generic_structure(
|
|
634
762
|
AST_NODE_T* node,
|
|
635
763
|
hb_array_T* array,
|
|
@@ -796,6 +924,28 @@ static size_t process_block_children(
|
|
|
796
924
|
return index;
|
|
797
925
|
}
|
|
798
926
|
|
|
927
|
+
hb_array_T* get_node_children_array(const AST_NODE_T* node) {
|
|
928
|
+
if (!node) { return NULL; }
|
|
929
|
+
|
|
930
|
+
switch (node->type) {
|
|
931
|
+
case AST_DOCUMENT_NODE: return ((AST_DOCUMENT_NODE_T*) node)->children;
|
|
932
|
+
case AST_HTML_ELEMENT_NODE: return ((AST_HTML_ELEMENT_NODE_T*) node)->body;
|
|
933
|
+
case AST_ERB_BLOCK_NODE: return ((AST_ERB_BLOCK_NODE_T*) node)->body;
|
|
934
|
+
case AST_ERB_IF_NODE: return ((AST_ERB_IF_NODE_T*) node)->statements;
|
|
935
|
+
case AST_ERB_UNLESS_NODE: return ((AST_ERB_UNLESS_NODE_T*) node)->statements;
|
|
936
|
+
case AST_ERB_ELSE_NODE: return ((AST_ERB_ELSE_NODE_T*) node)->statements;
|
|
937
|
+
case AST_ERB_WHILE_NODE: return ((AST_ERB_WHILE_NODE_T*) node)->statements;
|
|
938
|
+
case AST_ERB_UNTIL_NODE: return ((AST_ERB_UNTIL_NODE_T*) node)->statements;
|
|
939
|
+
case AST_ERB_FOR_NODE: return ((AST_ERB_FOR_NODE_T*) node)->statements;
|
|
940
|
+
case AST_ERB_BEGIN_NODE: return ((AST_ERB_BEGIN_NODE_T*) node)->statements;
|
|
941
|
+
case AST_ERB_RESCUE_NODE: return ((AST_ERB_RESCUE_NODE_T*) node)->statements;
|
|
942
|
+
case AST_ERB_ENSURE_NODE: return ((AST_ERB_ENSURE_NODE_T*) node)->statements;
|
|
943
|
+
case AST_ERB_CASE_NODE: return ((AST_ERB_CASE_NODE_T*) node)->children;
|
|
944
|
+
case AST_ERB_WHEN_NODE: return ((AST_ERB_WHEN_NODE_T*) node)->statements;
|
|
945
|
+
default: return NULL;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
799
949
|
hb_array_T* rewrite_node_array(AST_NODE_T* node, hb_array_T* array, analyze_ruby_context_T* context) {
|
|
800
950
|
hb_allocator_T* allocator = context->allocator;
|
|
801
951
|
hb_array_T* new_array = hb_array_init(hb_array_size(array), allocator);
|
|
@@ -862,6 +1012,10 @@ void herb_analyze_parse_tree(
|
|
|
862
1012
|
|
|
863
1013
|
if (options && options->render_nodes) { herb_visit_node((AST_NODE_T*) document, transform_render_nodes, &context); }
|
|
864
1014
|
|
|
1015
|
+
if (options && options->strict_locals) {
|
|
1016
|
+
herb_visit_node((AST_NODE_T*) document, transform_strict_locals_nodes, &context);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
865
1019
|
if (options && options->action_view_helpers) {
|
|
866
1020
|
herb_visit_node((AST_NODE_T*) document, transform_tag_helper_nodes, &context);
|
|
867
1021
|
}
|
|
@@ -877,7 +1031,7 @@ void herb_analyze_parse_tree(
|
|
|
877
1031
|
|
|
878
1032
|
herb_visit_node((AST_NODE_T*) document, detect_invalid_erb_structures, &invalid_context);
|
|
879
1033
|
|
|
880
|
-
herb_analyze_parse_errors(document, source, allocator);
|
|
1034
|
+
herb_analyze_parse_errors(document, source, options, allocator);
|
|
881
1035
|
|
|
882
1036
|
herb_parser_match_html_tags_post_analyze(document, options, allocator);
|
|
883
1037
|
|
data/src/analyze/analyzed_ruby.c
CHANGED
data/src/analyze/builders.c
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#include "../include/analyze/builders.h"
|
|
2
2
|
#include "../include/analyze/analyze.h"
|
|
3
|
-
#include "../include/ast_nodes.h"
|
|
4
|
-
#include "../include/
|
|
5
|
-
#include "../include/
|
|
6
|
-
#include "../include/
|
|
7
|
-
#include "../include/
|
|
8
|
-
#include "../include/
|
|
9
|
-
#include "../include/
|
|
10
|
-
#include "../include/
|
|
3
|
+
#include "../include/ast/ast_nodes.h"
|
|
4
|
+
#include "../include/lexer/token_struct.h"
|
|
5
|
+
#include "../include/lib/hb_allocator.h"
|
|
6
|
+
#include "../include/lib/hb_array.h"
|
|
7
|
+
#include "../include/lib/hb_string.h"
|
|
8
|
+
#include "../include/location/location.h"
|
|
9
|
+
#include "../include/location/position.h"
|
|
10
|
+
#include "../include/prism/prism_helpers.h"
|
|
11
11
|
|
|
12
12
|
#include <stddef.h>
|
|
13
13
|
#include <string.h>
|
|
@@ -322,6 +322,9 @@ 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
|
+
NULL,
|
|
326
|
+
NULL,
|
|
327
|
+
NULL,
|
|
325
328
|
context->end_node,
|
|
326
329
|
context->start_position,
|
|
327
330
|
context->end_position,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
#include "../include/analyze/conditional_elements.h"
|
|
2
|
-
#include "../include/ast_nodes.h"
|
|
3
|
-
#include "../include/element_source.h"
|
|
2
|
+
#include "../include/ast/ast_nodes.h"
|
|
4
3
|
#include "../include/errors.h"
|
|
5
|
-
#include "../include/token_struct.h"
|
|
6
|
-
#include "../include/
|
|
7
|
-
#include "../include/
|
|
8
|
-
#include "../include/
|
|
4
|
+
#include "../include/lexer/token_struct.h"
|
|
5
|
+
#include "../include/lib/hb_allocator.h"
|
|
6
|
+
#include "../include/lib/hb_array.h"
|
|
7
|
+
#include "../include/lib/hb_string.h"
|
|
9
8
|
#include "../include/visitor.h"
|
|
10
9
|
|
|
11
10
|
#include <stdbool.h>
|
|
@@ -365,7 +364,7 @@ static void rewrite_conditional_elements(hb_array_T* nodes, hb_array_T* document
|
|
|
365
364
|
(AST_NODE_T*) close_tag,
|
|
366
365
|
node,
|
|
367
366
|
matched_open->open_tag->tag_name,
|
|
368
|
-
|
|
367
|
+
hb_string("HTML"),
|
|
369
368
|
start_position,
|
|
370
369
|
end_position,
|
|
371
370
|
errors,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
#include "../include/analyze/conditional_open_tags.h"
|
|
2
|
-
#include "../include/ast_nodes.h"
|
|
3
|
-
#include "../include/element_source.h"
|
|
2
|
+
#include "../include/ast/ast_nodes.h"
|
|
4
3
|
#include "../include/errors.h"
|
|
5
|
-
#include "../include/token_struct.h"
|
|
6
|
-
#include "../include/
|
|
7
|
-
#include "../include/
|
|
8
|
-
#include "../include/
|
|
4
|
+
#include "../include/lexer/token_struct.h"
|
|
5
|
+
#include "../include/lib/hb_allocator.h"
|
|
6
|
+
#include "../include/lib/hb_array.h"
|
|
7
|
+
#include "../include/lib/hb_string.h"
|
|
9
8
|
#include "../include/visitor.h"
|
|
10
9
|
|
|
11
10
|
#include <stdbool.h>
|
|
@@ -409,7 +408,7 @@ static void rewrite_conditional_open_tags(hb_array_T* nodes, hb_array_T* documen
|
|
|
409
408
|
body,
|
|
410
409
|
(AST_NODE_T*) close_tag,
|
|
411
410
|
false,
|
|
412
|
-
|
|
411
|
+
hb_string("HTML"),
|
|
413
412
|
start_position,
|
|
414
413
|
end_position,
|
|
415
414
|
element_errors,
|
data/src/analyze/control_type.c
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#include "../include/analyze/analyze.h"
|
|
3
3
|
#include "../include/analyze/analyzed_ruby.h"
|
|
4
4
|
#include "../include/analyze/helpers.h"
|
|
5
|
-
#include "../include/ast_node.h"
|
|
5
|
+
#include "../include/ast/ast_node.h"
|
|
6
6
|
|
|
7
7
|
#include <prism.h>
|
|
8
8
|
#include <stdbool.h>
|
|
@@ -213,6 +213,7 @@ bool is_subsequent_type(control_type_t parent_type, control_type_t child_type) {
|
|
|
213
213
|
case CONTROL_TYPE_CASE:
|
|
214
214
|
case CONTROL_TYPE_CASE_MATCH: return child_type == CONTROL_TYPE_WHEN || child_type == CONTROL_TYPE_ELSE;
|
|
215
215
|
case CONTROL_TYPE_BEGIN:
|
|
216
|
+
case CONTROL_TYPE_BLOCK:
|
|
216
217
|
return child_type == CONTROL_TYPE_RESCUE || child_type == CONTROL_TYPE_ELSE || child_type == CONTROL_TYPE_ENSURE;
|
|
217
218
|
case CONTROL_TYPE_RESCUE: return child_type == CONTROL_TYPE_RESCUE;
|
|
218
219
|
case CONTROL_TYPE_UNLESS: return child_type == CONTROL_TYPE_ELSE;
|
|
@@ -227,7 +228,8 @@ bool is_terminator_type(control_type_t parent_type, control_type_t child_type) {
|
|
|
227
228
|
switch (parent_type) {
|
|
228
229
|
case CONTROL_TYPE_WHEN: return child_type == CONTROL_TYPE_WHEN || child_type == CONTROL_TYPE_ELSE;
|
|
229
230
|
case CONTROL_TYPE_IN: return child_type == CONTROL_TYPE_IN || child_type == CONTROL_TYPE_ELSE;
|
|
230
|
-
case CONTROL_TYPE_BLOCK:
|
|
231
|
+
case CONTROL_TYPE_BLOCK:
|
|
232
|
+
return child_type == CONTROL_TYPE_BLOCK_CLOSE || is_subsequent_type(parent_type, child_type);
|
|
231
233
|
|
|
232
234
|
default: return is_subsequent_type(parent_type, child_type);
|
|
233
235
|
}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
#include "../include/analyze/analyze.h"
|
|
3
3
|
#include "../include/analyze/analyzed_ruby.h"
|
|
4
4
|
#include "../include/analyze/helpers.h"
|
|
5
|
-
#include "../include/ast_node.h"
|
|
6
|
-
#include "../include/ast_nodes.h"
|
|
5
|
+
#include "../include/ast/ast_node.h"
|
|
6
|
+
#include "../include/ast/ast_nodes.h"
|
|
7
7
|
#include "../include/errors.h"
|
|
8
|
-
#include "../include/token_struct.h"
|
|
9
|
-
#include "../include/
|
|
10
|
-
#include "../include/
|
|
8
|
+
#include "../include/lexer/token_struct.h"
|
|
9
|
+
#include "../include/lib/hb_array.h"
|
|
10
|
+
#include "../include/lib/hb_string.h"
|
|
11
11
|
#include "../include/visitor.h"
|
|
12
12
|
|
|
13
13
|
#include <stdbool.h>
|
data/src/analyze/missing_end.c
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
#include "../include/analyze/helpers.h"
|
|
5
5
|
#include "../include/errors.h"
|
|
6
|
-
#include "../include/
|
|
7
|
-
#include "../include/
|
|
6
|
+
#include "../include/lib/hb_allocator.h"
|
|
7
|
+
#include "../include/lib/hb_string.h"
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
void check_erb_node_for_missing_end(const AST_NODE_T* node, hb_allocator_T* allocator) {
|
data/src/analyze/parse_errors.c
CHANGED
|
@@ -1,16 +1,47 @@
|
|
|
1
1
|
#include "../include/analyze/analyze.h"
|
|
2
|
-
#include "../include/ast_node.h"
|
|
3
|
-
#include "../include/ast_nodes.h"
|
|
2
|
+
#include "../include/ast/ast_node.h"
|
|
3
|
+
#include "../include/ast/ast_nodes.h"
|
|
4
4
|
#include "../include/errors.h"
|
|
5
5
|
#include "../include/extract.h"
|
|
6
|
-
#include "../include/
|
|
7
|
-
#include "../include/
|
|
8
|
-
#include "../include/
|
|
6
|
+
#include "../include/lib/hb_allocator.h"
|
|
7
|
+
#include "../include/lib/hb_string.h"
|
|
8
|
+
#include "../include/prism/prism_helpers.h"
|
|
9
9
|
|
|
10
10
|
#include <prism.h>
|
|
11
11
|
#include <stdlib.h>
|
|
12
12
|
#include <string.h>
|
|
13
13
|
|
|
14
|
+
static bool document_has_anonymous_keyword_rest(AST_DOCUMENT_NODE_T* document) {
|
|
15
|
+
if (!document || !document->children) { return false; }
|
|
16
|
+
|
|
17
|
+
for (size_t index = 0; index < hb_array_size(document->children); index++) {
|
|
18
|
+
AST_NODE_T* child = hb_array_get(document->children, index);
|
|
19
|
+
if (!child || child->type != AST_ERB_STRICT_LOCALS_NODE) { continue; }
|
|
20
|
+
|
|
21
|
+
AST_ERB_STRICT_LOCALS_NODE_T* strict_locals_node = (AST_ERB_STRICT_LOCALS_NODE_T*) child;
|
|
22
|
+
if (!strict_locals_node->locals) { continue; }
|
|
23
|
+
|
|
24
|
+
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; }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static bool should_skip_forwarding_error(
|
|
34
|
+
const pm_diagnostic_t* error,
|
|
35
|
+
bool strict_locals_enabled,
|
|
36
|
+
bool has_anonymous_keyword_rest
|
|
37
|
+
) {
|
|
38
|
+
if (error->diag_id != PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR) { return false; }
|
|
39
|
+
|
|
40
|
+
if (!strict_locals_enabled) { return true; }
|
|
41
|
+
|
|
42
|
+
return has_anonymous_keyword_rest;
|
|
43
|
+
}
|
|
44
|
+
|
|
14
45
|
static void parse_erb_content_errors(AST_NODE_T* erb_node, const char* source, hb_allocator_T* allocator) {
|
|
15
46
|
if (!erb_node || erb_node->type != AST_ERB_CONTENT_NODE) { return; }
|
|
16
47
|
AST_ERB_CONTENT_NODE_T* content_node = (AST_ERB_CONTENT_NODE_T*) erb_node;
|
|
@@ -45,11 +76,19 @@ static void parse_erb_content_errors(AST_NODE_T* erb_node, const char* source, h
|
|
|
45
76
|
free(content);
|
|
46
77
|
}
|
|
47
78
|
|
|
48
|
-
void herb_analyze_parse_errors(
|
|
79
|
+
void herb_analyze_parse_errors(
|
|
80
|
+
AST_DOCUMENT_NODE_T* document,
|
|
81
|
+
const char* source,
|
|
82
|
+
const parser_options_T* parser_options,
|
|
83
|
+
hb_allocator_T* allocator
|
|
84
|
+
) {
|
|
49
85
|
char* extracted_ruby = herb_extract_ruby_with_semicolons(source, allocator);
|
|
50
86
|
|
|
51
87
|
if (!extracted_ruby) { return; }
|
|
52
88
|
|
|
89
|
+
bool strict_locals_enabled = parser_options && parser_options->strict_locals;
|
|
90
|
+
bool has_anonymous_keyword_rest = strict_locals_enabled && document_has_anonymous_keyword_rest(document);
|
|
91
|
+
|
|
53
92
|
pm_parser_t parser;
|
|
54
93
|
pm_options_t options = { 0, .partial_script = true };
|
|
55
94
|
pm_parser_init(&parser, (const uint8_t*) extracted_ruby, strlen(extracted_ruby), &options);
|
|
@@ -58,6 +97,8 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source
|
|
|
58
97
|
|
|
59
98
|
for (const pm_diagnostic_t* error = (const pm_diagnostic_t*) parser.error_list.head; error != NULL;
|
|
60
99
|
error = (const pm_diagnostic_t*) error->node.next) {
|
|
100
|
+
if (should_skip_forwarding_error(error, strict_locals_enabled, has_anonymous_keyword_rest)) { continue; }
|
|
101
|
+
|
|
61
102
|
size_t error_offset = (size_t) (error->location.start - parser.start);
|
|
62
103
|
|
|
63
104
|
if (strstr(error->message, "unexpected ';'") != NULL) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#include "../include/analyze/prism_annotate.h"
|
|
2
|
-
#include "../include/ast_node.h"
|
|
3
|
-
#include "../include/ast_nodes.h"
|
|
2
|
+
#include "../include/ast/ast_node.h"
|
|
3
|
+
#include "../include/ast/ast_nodes.h"
|
|
4
4
|
#include "../include/extract.h"
|
|
5
|
-
#include "../include/
|
|
6
|
-
#include "../include/
|
|
7
|
-
#include "../include/
|
|
8
|
-
#include "../include/
|
|
9
|
-
#include "../include/
|
|
5
|
+
#include "../include/lib/hb_allocator.h"
|
|
6
|
+
#include "../include/lib/hb_buffer.h"
|
|
7
|
+
#include "../include/lib/hb_narray.h"
|
|
8
|
+
#include "../include/prism/herb_prism_node.h"
|
|
9
|
+
#include "../include/prism/prism_context.h"
|
|
10
10
|
#include "../include/visitor.h"
|
|
11
11
|
|
|
12
12
|
#include <prism.h>
|
data/src/analyze/render_nodes.c
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
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/ast_nodes.h"
|
|
5
|
+
#include "../include/ast/ast_nodes.h"
|
|
6
6
|
#include "../include/errors.h"
|
|
7
|
-
#include "../include/
|
|
8
|
-
#include "../include/
|
|
9
|
-
#include "../include/
|
|
10
|
-
#include "../include/
|
|
7
|
+
#include "../include/lib/hb_allocator.h"
|
|
8
|
+
#include "../include/lib/hb_array.h"
|
|
9
|
+
#include "../include/lib/hb_string.h"
|
|
10
|
+
#include "../include/lib/string.h"
|
|
11
11
|
#include "../include/visitor.h"
|
|
12
12
|
|
|
13
13
|
#include <prism.h>
|
|
@@ -727,27 +727,7 @@ static void transform_render_nodes_in_array(hb_array_T* array, analyze_ruby_cont
|
|
|
727
727
|
static void transform_render_in_node(const AST_NODE_T* node, analyze_ruby_context_T* context) {
|
|
728
728
|
if (!node || !context) { return; }
|
|
729
729
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
switch (node->type) {
|
|
733
|
-
case AST_DOCUMENT_NODE: array = ((AST_DOCUMENT_NODE_T*) node)->children; break;
|
|
734
|
-
case AST_HTML_ELEMENT_NODE: array = ((AST_HTML_ELEMENT_NODE_T*) node)->body; break;
|
|
735
|
-
case AST_ERB_BLOCK_NODE: array = ((AST_ERB_BLOCK_NODE_T*) node)->body; break;
|
|
736
|
-
case AST_ERB_IF_NODE: array = ((AST_ERB_IF_NODE_T*) node)->statements; break;
|
|
737
|
-
case AST_ERB_UNLESS_NODE: array = ((AST_ERB_UNLESS_NODE_T*) node)->statements; break;
|
|
738
|
-
case AST_ERB_ELSE_NODE: array = ((AST_ERB_ELSE_NODE_T*) node)->statements; break;
|
|
739
|
-
case AST_ERB_WHILE_NODE: array = ((AST_ERB_WHILE_NODE_T*) node)->statements; break;
|
|
740
|
-
case AST_ERB_UNTIL_NODE: array = ((AST_ERB_UNTIL_NODE_T*) node)->statements; break;
|
|
741
|
-
case AST_ERB_FOR_NODE: array = ((AST_ERB_FOR_NODE_T*) node)->statements; break;
|
|
742
|
-
case AST_ERB_BEGIN_NODE: array = ((AST_ERB_BEGIN_NODE_T*) node)->statements; break;
|
|
743
|
-
case AST_ERB_RESCUE_NODE: array = ((AST_ERB_RESCUE_NODE_T*) node)->statements; break;
|
|
744
|
-
case AST_ERB_ENSURE_NODE: array = ((AST_ERB_ENSURE_NODE_T*) node)->statements; break;
|
|
745
|
-
case AST_ERB_CASE_NODE: array = ((AST_ERB_CASE_NODE_T*) node)->children; break;
|
|
746
|
-
case AST_ERB_WHEN_NODE: array = ((AST_ERB_WHEN_NODE_T*) node)->statements; break;
|
|
747
|
-
default: return;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
transform_render_nodes_in_array(array, context);
|
|
730
|
+
transform_render_nodes_in_array(get_node_children_array(node), context);
|
|
751
731
|
}
|
|
752
732
|
|
|
753
733
|
bool transform_render_nodes(const AST_NODE_T* node, void* data) {
|