herb 0.11.1 → 0.11.2
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/Rakefile +4 -2
- data/config.yml +6 -0
- data/ext/herb/extconf.rb +8 -31
- data/ext/herb/nodes.c +75 -75
- data/ext/herb/parser_options_helpers.c +26 -0
- data/lib/herb/analysis/partial_index.rb +1 -1
- data/lib/herb/analysis/partial_resolution.rb +27 -0
- data/lib/herb/ast/helpers.rb +1 -1
- data/lib/herb/configuration.rb +11 -1
- data/lib/herb/dev/classifier.rb +1 -1
- data/lib/herb/engine/compiler.rb +5 -8
- data/lib/herb/engine/slots/dynamics_compiler.rb +53 -14
- data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
- data/lib/herb/engine/slots/visitor.rb +32 -4
- data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
- data/lib/herb/parser_options.rb +6 -3
- data/lib/herb/project.rb +19 -8
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +1 -1
- data/sig/herb/analysis/partial_resolution.rbs +8 -0
- data/sig/herb/configuration.rbs +3 -0
- data/sig/herb/engine/slots/dynamics_compiler.rbs +24 -7
- data/sig/herb/engine/slots/visitor.rbs +14 -0
- data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
- data/sig/herb/parser_options.rbs +6 -4
- data/sig/herb.rbs +2 -2
- data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
- data/src/analyze/action_view/generated_handlers.c +36 -36
- data/src/analyze/action_view/image_tag.c +7 -3
- data/src/analyze/action_view/javascript_include_tag.c +6 -3
- data/src/analyze/action_view/link_to.c +23 -23
- data/src/analyze/action_view/registry.c +7 -3
- data/src/analyze/action_view/tag_helper_node_builders.c +6 -13
- data/src/analyze/action_view/tag_helpers.c +139 -90
- data/src/analyze/action_view/turbo_frame_tag.c +5 -4
- data/src/analyze/analyze.c +35 -19
- data/src/analyze/analyze_helpers.c +161 -188
- data/src/analyze/analyzed_ruby.c +8 -7
- data/src/analyze/control_type.c +29 -22
- data/src/analyze/herb_directives.c +16 -20
- data/src/analyze/iteration_nodes.c +69 -24
- data/src/analyze/parse_errors.c +32 -22
- data/src/analyze/postfix_conditionals.c +23 -13
- data/src/analyze/prism_annotate.c +29 -28
- data/src/analyze/render_nodes.c +51 -41
- data/src/analyze/strict_locals.c +14 -15
- data/src/analyze/ternary_conditionals.c +14 -10
- data/src/herb.c +10 -8
- data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
- data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
- data/src/include/analyze/action_view/tag_helpers.h +1 -1
- data/src/include/analyze/analyze.h +3 -2
- data/src/include/analyze/analyzed_ruby.h +4 -2
- data/src/include/analyze/helpers.h +6 -6
- data/src/include/herb.h +3 -2
- data/src/include/parser/parser_options.h +5 -0
- data/src/include/prism/prism_context.h +12 -12
- data/src/include/prism/prism_helpers.h +30 -0
- data/src/include/prism_version.h +11 -0
- data/src/include/version.h +1 -1
- data/src/parser/parser_helpers.c +1 -2
- data/src/parser.c +6 -7
- data/src/parser_options_defaults.c +1 -0
- data/src/prism/prism_helpers.c +84 -50
- data/src/prism/ruby_parser.c +20 -20
- data/templates/ext/herb/nodes.c.erb +5 -5
- data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
- data/templates/java/nodes.c.erb +6 -6
- data/templates/java/parser_options_helpers.c.erb +41 -2
- data/templates/java/parser_options_helpers.h.erb +2 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
- data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
- data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
- data/templates/lib/herb/parser_options.rb.erb +1 -1
- data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
- data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
- data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
- data/templates/src/include/parser/parser_options.h.erb +10 -0
- data/templates/src/include/prism_version.h.erb +17 -0
- data/templates/src/parser_options_defaults.c.erb +1 -1
- data/templates/template.rb +17 -2
- data/templates/wasm/nodes.cpp.erb +5 -5
- data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
- data/vendor/prism/Rakefile +76 -7
- data/vendor/prism/config.yml +174 -161
- data/vendor/prism/include/prism/arena.h +45 -0
- data/vendor/prism/include/prism/arena.hpp +42 -0
- data/vendor/prism/include/prism/ast.h +2738 -611
- data/vendor/prism/include/prism/ast.hpp +641 -0
- data/vendor/prism/include/prism/buffer.h +60 -0
- data/vendor/prism/include/prism/buffer.hpp +55 -0
- data/vendor/prism/include/prism/comments.h +72 -0
- data/vendor/prism/include/prism/compiler/accel.h +26 -0
- data/vendor/prism/include/prism/compiler/align.h +36 -0
- data/vendor/prism/include/prism/compiler/assume.h +25 -0
- data/vendor/prism/include/prism/compiler/branch.h +26 -0
- data/vendor/prism/include/prism/compiler/bswap.h +46 -0
- data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
- data/vendor/prism/include/prism/compiler/endianness.h +34 -0
- data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
- data/vendor/prism/include/prism/compiler/exported.h +24 -0
- data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
- data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
- data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
- data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
- data/vendor/prism/include/prism/compiler/format.h +27 -0
- data/vendor/prism/include/prism/compiler/inline.h +17 -0
- data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
- data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
- data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
- data/vendor/prism/include/prism/compiler/unused.h +18 -0
- data/vendor/prism/include/prism/constant_pool.h +106 -0
- data/vendor/prism/include/prism/diagnostic.h +55 -402
- data/vendor/prism/include/prism/errors_format.h +61 -0
- data/vendor/prism/include/prism/excludes.h +29 -0
- data/vendor/prism/include/prism/integer.h +41 -0
- data/vendor/prism/include/prism/internal/allocator.h +68 -0
- data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
- data/vendor/prism/include/prism/internal/arena.h +108 -0
- data/vendor/prism/include/prism/internal/bit.h +42 -0
- data/vendor/prism/include/prism/internal/buffer.h +94 -0
- data/vendor/prism/include/prism/internal/char.h +145 -0
- data/vendor/prism/include/prism/internal/comments.h +54 -0
- data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
- data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
- data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
- data/vendor/prism/include/prism/internal/integer.h +68 -0
- data/vendor/prism/include/prism/internal/isinf.h +16 -0
- data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
- data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
- data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
- data/vendor/prism/include/prism/internal/memchr.h +15 -0
- data/vendor/prism/include/prism/internal/node.h +42 -0
- data/vendor/prism/include/prism/internal/options.h +232 -0
- data/vendor/prism/include/prism/internal/parser.h +1015 -0
- data/vendor/prism/include/prism/internal/regexp.h +26 -0
- data/vendor/prism/include/prism/internal/serialize.h +39 -0
- data/vendor/prism/include/prism/internal/source.h +72 -0
- data/vendor/prism/include/prism/internal/static_literals.h +60 -0
- data/vendor/prism/include/prism/internal/stringy.h +30 -0
- data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
- data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
- data/vendor/prism/include/prism/internal/tokens.h +11 -0
- data/vendor/prism/include/prism/internal/xxh3.h +16 -0
- data/vendor/prism/include/prism/json.h +40 -0
- data/vendor/prism/include/prism/line_offset_list.h +69 -0
- data/vendor/prism/include/prism/magic_comments.h +53 -0
- data/vendor/prism/include/prism/node.h +59 -49
- data/vendor/prism/include/prism/node.hpp +272 -0
- data/vendor/prism/include/prism/node_type.hpp +38 -0
- data/vendor/prism/include/prism/options.h +154 -279
- data/vendor/prism/include/prism/options.hpp +43 -0
- data/vendor/prism/include/prism/parser.h +367 -870
- data/vendor/prism/include/prism/parser.hpp +274 -0
- data/vendor/prism/include/prism/prettyprint.h +14 -9
- data/vendor/prism/include/prism/serialize.h +123 -0
- data/vendor/prism/include/prism/source.h +163 -0
- data/vendor/prism/include/prism/stream.h +36 -0
- data/vendor/prism/include/prism/string_query.h +82 -0
- data/vendor/prism/include/prism/stringy.h +61 -0
- data/vendor/prism/include/prism/stringy.hpp +31 -0
- data/vendor/prism/include/prism/version.h +20 -3
- data/vendor/prism/include/prism.h +35 -320
- data/vendor/prism/include/prism.hpp +24 -0
- data/vendor/prism/src/arena.c +122 -0
- data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
- data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
- data/vendor/prism/src/comments.c +455 -0
- data/vendor/prism/src/constant_pool.c +406 -0
- data/vendor/prism/src/diagnostic.c +120 -68
- data/vendor/prism/src/encoding.c +8 -3
- data/vendor/prism/src/errors_format.c +519 -0
- data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
- data/vendor/prism/src/json.c +5733 -0
- data/vendor/prism/src/line_offset_list.c +100 -0
- data/vendor/prism/src/list.c +24 -0
- data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
- data/vendor/prism/src/node.c +3465 -7787
- data/vendor/prism/src/options.c +161 -54
- data/vendor/prism/src/parser.c +371 -0
- data/vendor/prism/src/prettyprint.c +421 -354
- data/vendor/prism/src/prism.c +8522 -7280
- data/vendor/prism/src/regexp.c +960 -45
- data/vendor/prism/src/serialize.c +2434 -2048
- data/vendor/prism/src/source.c +524 -0
- data/vendor/prism/src/static_literals.c +303 -360
- data/vendor/prism/src/string_query.c +180 -0
- data/vendor/prism/src/stringy.c +61 -0
- data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
- data/vendor/prism/src/strpbrk.c +447 -0
- data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
- data/vendor/prism/src/xxh3.c +292 -0
- data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
- data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
- data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
- data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
- data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
- data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
- data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
- data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
- data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
- data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
- data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
- data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
- data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
- data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
- data/vendor/prism/templates/src/json.c.erb +130 -0
- data/vendor/prism/templates/src/node.c.erb +79 -236
- data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
- data/vendor/prism/templates/src/serialize.c.erb +369 -183
- data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
- data/vendor/prism/templates/template.rb +193 -91
- metadata +100 -42
- data/vendor/prism/include/prism/defines.h +0 -260
- data/vendor/prism/include/prism/pack.h +0 -163
- data/vendor/prism/include/prism/regexp.h +0 -43
- data/vendor/prism/include/prism/static_literals.h +0 -121
- data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
- data/vendor/prism/include/prism/util/pm_char.h +0 -204
- data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
- data/vendor/prism/include/prism/util/pm_integer.h +0 -130
- data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
- data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
- data/vendor/prism/include/prism/util/pm_string.h +0 -200
- data/vendor/prism/src/pack.c +0 -509
- data/vendor/prism/src/util/pm_constant_pool.c +0 -342
- data/vendor/prism/src/util/pm_list.c +0 -49
- data/vendor/prism/src/util/pm_newline_list.c +0 -125
- data/vendor/prism/src/util/pm_string.c +0 -381
- data/vendor/prism/src/util/pm_strpbrk.c +0 -206
- data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
- data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
- data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
- data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
- data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
- data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
- data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
- data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
- data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
- data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
data/src/prism/ruby_parser.c
CHANGED
|
@@ -2,51 +2,51 @@
|
|
|
2
2
|
|
|
3
3
|
#include <prism.h>
|
|
4
4
|
#include <stdbool.h>
|
|
5
|
+
#include <stdio.h>
|
|
5
6
|
#include <stdlib.h>
|
|
6
7
|
#include <string.h>
|
|
7
8
|
|
|
8
|
-
static
|
|
9
|
+
static pm_visit_result_t herb_prism_visit(const pm_node_t* node, void* data) {
|
|
9
10
|
const size_t* indent = (size_t*) data;
|
|
10
11
|
|
|
11
12
|
for (size_t i = 0; i < *indent * 2; i++) {
|
|
12
13
|
putc(' ', stdout);
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
printf("%s\n",
|
|
16
|
+
printf("%s\n", pm_node_type(node->type));
|
|
16
17
|
|
|
17
18
|
size_t next_indent = *indent + 1;
|
|
18
19
|
size_t* next_data = &next_indent;
|
|
19
20
|
pm_visit_child_nodes(node, herb_prism_visit, next_data);
|
|
20
21
|
|
|
21
|
-
return
|
|
22
|
+
return PM_VISIT_SKIP;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
void herb_parse_ruby_to_stdout(char* source) {
|
|
25
26
|
size_t length = strlen(source);
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
pm_arena_t* arena = pm_arena_new();
|
|
29
|
+
pm_parser_t* parser = pm_parser_new(arena, (const uint8_t*) source, length, NULL);
|
|
29
30
|
|
|
30
|
-
pm_buffer_t buffer;
|
|
31
|
-
pm_buffer_init(&buffer);
|
|
31
|
+
pm_buffer_t* buffer = pm_buffer_new();
|
|
32
32
|
|
|
33
33
|
size_t indent = 0;
|
|
34
|
-
pm_node_t* root = pm_parse(
|
|
34
|
+
pm_node_t* root = pm_parse(parser);
|
|
35
35
|
size_t* data = &indent;
|
|
36
36
|
|
|
37
|
-
const char* root_type =
|
|
37
|
+
const char* root_type = pm_node_type(root->type);
|
|
38
38
|
printf("Root Type: %s\n", root_type);
|
|
39
39
|
|
|
40
40
|
pm_visit_node(root, herb_prism_visit, data);
|
|
41
41
|
|
|
42
42
|
#ifndef PRISM_EXCLUDE_PRETTYPRINT
|
|
43
|
-
pm_prettyprint(
|
|
44
|
-
printf("
|
|
43
|
+
pm_prettyprint(buffer, parser, root);
|
|
44
|
+
printf("%.*s\n", (int) pm_buffer_length(buffer), pm_buffer_value(buffer));
|
|
45
45
|
#endif
|
|
46
46
|
|
|
47
|
-
pm_buffer_free(
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
pm_buffer_free(buffer);
|
|
48
|
+
pm_parser_free(parser);
|
|
49
|
+
pm_arena_free(arena);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
static const char* const RUBY_FRAGMENT_PREFIXES[] = {
|
|
@@ -56,14 +56,14 @@ static const char* const RUBY_FRAGMENT_PREFIXES[] = {
|
|
|
56
56
|
static const char* const RUBY_FRAGMENT_SUFFIXES[] = { "", "\nend", "", "\nend", "\nend", "\nend" };
|
|
57
57
|
|
|
58
58
|
static bool ruby_source_parses(const char* source, size_t length) {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
pm_arena_t* arena = pm_arena_new();
|
|
60
|
+
pm_parser_t* parser = pm_parser_new(arena, (const uint8_t*) source, length, NULL);
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
bool parses = (parser
|
|
62
|
+
pm_parse(parser);
|
|
63
|
+
bool parses = (pm_parser_errors_size(parser) == 0);
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
pm_parser_free(parser);
|
|
66
|
+
pm_arena_free(arena);
|
|
67
67
|
|
|
68
68
|
return parses;
|
|
69
69
|
}
|
|
@@ -69,17 +69,17 @@ static VALUE rb_<%= node.human %>_from_c_struct(<%= node.struct_type %>* <%= nod
|
|
|
69
69
|
<%- when Herb::Template::PrismNodeField -%>
|
|
70
70
|
VALUE <%= node.human %>_<%= field.name %>;
|
|
71
71
|
if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
|
|
72
|
-
pm_buffer_t pm_buffer =
|
|
73
|
-
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>,
|
|
72
|
+
pm_buffer_t* pm_buffer = pm_buffer_new();
|
|
73
|
+
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, pm_buffer);
|
|
74
74
|
|
|
75
|
-
if (pm_buffer
|
|
76
|
-
<%= node.human %>_<%= field.name %> = rb_str_new(pm_buffer
|
|
75
|
+
if (pm_buffer_length(pm_buffer) > 0) {
|
|
76
|
+
<%= node.human %>_<%= field.name %> = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
|
|
77
77
|
rb_enc_associate(<%= node.human %>_<%= field.name %>, rb_ascii8bit_encoding());
|
|
78
78
|
OBJ_FREEZE(<%= node.human %>_<%= field.name %>);
|
|
79
79
|
} else {
|
|
80
80
|
<%= node.human %>_<%= field.name %> = Qnil;
|
|
81
81
|
}
|
|
82
|
-
pm_buffer_free(
|
|
82
|
+
pm_buffer_free(pm_buffer);
|
|
83
83
|
} else {
|
|
84
84
|
<%= node.human %>_<%= field.name %> = Qnil;
|
|
85
85
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#include "parser_options_helpers.h"
|
|
2
2
|
|
|
3
|
+
#include <string.h>
|
|
4
|
+
|
|
3
5
|
void herb_extract_parser_options(VALUE options, parser_options_T* parser_options) {
|
|
4
6
|
if (NIL_P(options)) { return; }
|
|
5
7
|
<%- parser_options.extractable_fields_for(:ruby).each do |field| -%>
|
|
@@ -10,6 +12,31 @@ void herb_extract_parser_options(VALUE options, parser_options_T* parser_options
|
|
|
10
12
|
if (NIL_P(value)) { value = rb_hash_lookup(options, ID2SYM(rb_intern("<%= field.snake_case %>"))); }
|
|
11
13
|
if (!NIL_P(value)) { parser_options-><%= field.c_name %> = RTEST(value); }
|
|
12
14
|
}
|
|
15
|
+
<%- elsif field.string? -%>
|
|
16
|
+
{
|
|
17
|
+
VALUE value = rb_hash_lookup(options, rb_utf8_str_new_cstr("<%= field.snake_case %>"));
|
|
18
|
+
if (NIL_P(value)) { value = rb_hash_lookup(options, ID2SYM(rb_intern("<%= field.snake_case %>"))); }
|
|
19
|
+
|
|
20
|
+
if (!NIL_P(value)) {
|
|
21
|
+
Check_Type(value, T_STRING);
|
|
22
|
+
|
|
23
|
+
const char* data = RSTRING_PTR(value);
|
|
24
|
+
size_t length = (size_t) RSTRING_LEN(value);
|
|
25
|
+
|
|
26
|
+
<%- if field.validator -%>
|
|
27
|
+
if (!<%= field.validator %>(data, length)) {
|
|
28
|
+
rb_raise(rb_eArgError, "<%= field.snake_case %> %+" PRIsVALUE " is not supported", value);
|
|
29
|
+
}
|
|
30
|
+
<%- else -%>
|
|
31
|
+
if (length >= HERB_PARSER_OPTIONS_STRING_CAPACITY) {
|
|
32
|
+
rb_raise(rb_eArgError, "<%= field.snake_case %> must be shorter than %d bytes", HERB_PARSER_OPTIONS_STRING_CAPACITY);
|
|
33
|
+
}
|
|
34
|
+
<%- end -%>
|
|
35
|
+
|
|
36
|
+
memcpy(parser_options-><%= field.c_name %>, data, length);
|
|
37
|
+
parser_options-><%= field.c_name %>[length] = '\0';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
13
40
|
<%- elsif field.ruby_unit == "seconds" -%>
|
|
14
41
|
{
|
|
15
42
|
VALUE value = rb_hash_lookup(options, rb_utf8_str_new_cstr("<%= field.snake_case %>"));
|
|
@@ -52,6 +79,12 @@ VALUE herb_build_parser_options_hash(const parser_options_T* options) {
|
|
|
52
79
|
|
|
53
80
|
rb_hash_aset(kwargs, ID2SYM(rb_intern("<%= field.snake_case %>")), <%= field.snake_case %>);
|
|
54
81
|
}
|
|
82
|
+
<%- elsif field.string? -%>
|
|
83
|
+
rb_hash_aset(
|
|
84
|
+
kwargs,
|
|
85
|
+
ID2SYM(rb_intern("<%= field.snake_case %>")),
|
|
86
|
+
options-><%= field.c_name %>[0] == '\0' ? Qnil : rb_utf8_str_new_cstr(options-><%= field.c_name %>)
|
|
87
|
+
);
|
|
55
88
|
<%- elsif field.ruby_unit == "seconds" -%>
|
|
56
89
|
rb_hash_aset(kwargs, ID2SYM(rb_intern("<%= field.snake_case %>")), DBL2NUM((double) options-><%= field.c_name %> / 1000.0));
|
|
57
90
|
<%- elsif field.nullable? -%>
|
data/templates/java/nodes.c.erb
CHANGED
|
@@ -49,15 +49,15 @@ jobject <%= node.name %>FromCStruct(JNIEnv* env, <%= node.struct_type %>* <%= no
|
|
|
49
49
|
<%- elsif field.is_a?(Herb::Template::PrismNodeField) -%>
|
|
50
50
|
jbyteArray <%= field.name %>;
|
|
51
51
|
if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
|
|
52
|
-
pm_buffer_t pm_buffer =
|
|
53
|
-
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>,
|
|
54
|
-
if (pm_buffer
|
|
55
|
-
<%= field.name %> = (*env)->NewByteArray(env, (jsize)pm_buffer
|
|
56
|
-
(*env)->SetByteArrayRegion(env, <%= field.name %>, 0, (jsize)pm_buffer
|
|
52
|
+
pm_buffer_t* pm_buffer = pm_buffer_new();
|
|
53
|
+
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, pm_buffer);
|
|
54
|
+
if (pm_buffer_length(pm_buffer) > 0) {
|
|
55
|
+
<%= field.name %> = (*env)->NewByteArray(env, (jsize)pm_buffer_length(pm_buffer));
|
|
56
|
+
(*env)->SetByteArrayRegion(env, <%= field.name %>, 0, (jsize)pm_buffer_length(pm_buffer), (const jbyte*)pm_buffer_value(pm_buffer));
|
|
57
57
|
} else {
|
|
58
58
|
<%= field.name %> = NULL;
|
|
59
59
|
}
|
|
60
|
-
pm_buffer_free(
|
|
60
|
+
pm_buffer_free(pm_buffer);
|
|
61
61
|
} else {
|
|
62
62
|
<%= field.name %> = NULL;
|
|
63
63
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#include "parser_options_helpers.h"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <string.h>
|
|
5
|
+
|
|
6
|
+
bool herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T* parser_options) {
|
|
7
|
+
if (options == NULL) { return true; }
|
|
5
8
|
|
|
6
9
|
jclass optionsClass = (*env)->GetObjectClass(env, options);
|
|
7
10
|
<%- parser_options.extractable_fields_for(:java).each do |field| -%>
|
|
@@ -15,6 +18,40 @@ void herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T*
|
|
|
15
18
|
parser_options-><%= field.c_name %> = (value == JNI_TRUE);
|
|
16
19
|
}
|
|
17
20
|
}
|
|
21
|
+
<%- elsif field.string? -%>
|
|
22
|
+
{
|
|
23
|
+
jmethodID method = (*env)->GetMethodID(env, optionsClass, "<%= field.java_getter %>", "<%= field.java_jni_signature %>");
|
|
24
|
+
|
|
25
|
+
if (method != NULL) {
|
|
26
|
+
jstring value = (jstring) (*env)->CallObjectMethod(env, options, method);
|
|
27
|
+
|
|
28
|
+
if (value != NULL) {
|
|
29
|
+
const char* string = (*env)->GetStringUTFChars(env, value, NULL);
|
|
30
|
+
size_t length = strlen(string);
|
|
31
|
+
|
|
32
|
+
<%- if field.validator -%>
|
|
33
|
+
if (!<%= field.validator %>(string, length)) {
|
|
34
|
+
char message[96];
|
|
35
|
+
snprintf(message, sizeof(message), "<%= field.snake_case %> \"%.32s\" is not supported", string);
|
|
36
|
+
(*env)->ReleaseStringUTFChars(env, value, string);
|
|
37
|
+
(*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/IllegalArgumentException"), message);
|
|
38
|
+
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
<%- else -%>
|
|
42
|
+
if (length >= HERB_PARSER_OPTIONS_STRING_CAPACITY) {
|
|
43
|
+
(*env)->ReleaseStringUTFChars(env, value, string);
|
|
44
|
+
(*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/IllegalArgumentException"), "<%= field.snake_case %> is too long");
|
|
45
|
+
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
<%- end -%>
|
|
49
|
+
|
|
50
|
+
memcpy(parser_options-><%= field.c_name %>, string, length + 1);
|
|
51
|
+
(*env)->ReleaseStringUTFChars(env, value, string);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
18
55
|
<%- elsif field.nullable? -%>
|
|
19
56
|
{
|
|
20
57
|
jmethodID method = (*env)->GetMethodID(env, optionsClass, "<%= field.java_getter %>", "<%= field.java_jni_signature %>");
|
|
@@ -42,4 +79,6 @@ void herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T*
|
|
|
42
79
|
}
|
|
43
80
|
<%- end -%>
|
|
44
81
|
<%- end -%>
|
|
82
|
+
|
|
83
|
+
return true;
|
|
45
84
|
}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
#include "../src/include/parser/parser_options.h"
|
|
5
5
|
|
|
6
6
|
#include <jni.h>
|
|
7
|
+
#include <stdbool.h>
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
bool herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T* parser_options);
|
|
9
10
|
|
|
10
11
|
#endif
|
|
@@ -89,17 +89,17 @@ napi_value <%= node.human %>NodeFromCStruct(napi_env env, <%= node.struct_type %
|
|
|
89
89
|
<%- when Herb::Template::PrismNodeField -%>
|
|
90
90
|
napi_value <%= field.name %>;
|
|
91
91
|
if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
|
|
92
|
-
pm_buffer_t pm_buffer =
|
|
93
|
-
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>,
|
|
92
|
+
pm_buffer_t* pm_buffer = pm_buffer_new();
|
|
93
|
+
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, pm_buffer);
|
|
94
94
|
|
|
95
|
-
if (pm_buffer
|
|
95
|
+
if (pm_buffer_length(pm_buffer) > 0) {
|
|
96
96
|
void* buffer_data;
|
|
97
|
-
napi_create_buffer_copy(env, pm_buffer
|
|
97
|
+
napi_create_buffer_copy(env, pm_buffer_length(pm_buffer), pm_buffer_value(pm_buffer), &buffer_data, &<%= field.name %>);
|
|
98
98
|
} else {
|
|
99
99
|
napi_get_null(env, &<%= field.name %>);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
pm_buffer_free(
|
|
102
|
+
pm_buffer_free(pm_buffer);
|
|
103
103
|
} else {
|
|
104
104
|
napi_get_null(env, &<%= field.name %>);
|
|
105
105
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#include "parser_options_helpers.h"
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
#include <cstring>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
bool herb_extract_parser_options(napi_env env, napi_value options, parser_options_T* parser_options) {
|
|
4
7
|
napi_valuetype valuetype;
|
|
5
8
|
napi_typeof(env, options, &valuetype);
|
|
6
9
|
|
|
7
|
-
if (valuetype != napi_object) { return; }
|
|
10
|
+
if (valuetype != napi_object) { return true; }
|
|
8
11
|
<%- parser_options.extractable_fields_for(:javascript).each do |field| -%>
|
|
9
12
|
|
|
10
13
|
{
|
|
@@ -19,6 +22,33 @@ void herb_extract_parser_options(napi_env env, napi_value options, parser_option
|
|
|
19
22
|
bool value = false;
|
|
20
23
|
napi_get_value_bool(env, property, &value);
|
|
21
24
|
parser_options-><%= field.c_name %> = value;
|
|
25
|
+
<%- elsif field.string? -%>
|
|
26
|
+
napi_valuetype property_type;
|
|
27
|
+
napi_typeof(env, property, &property_type);
|
|
28
|
+
|
|
29
|
+
if (property_type == napi_string) {
|
|
30
|
+
size_t length = 0;
|
|
31
|
+
napi_get_value_string_utf8(env, property, nullptr, 0, &length);
|
|
32
|
+
|
|
33
|
+
std::string value(length, '\0');
|
|
34
|
+
napi_get_value_string_utf8(env, property, &value[0], length + 1, &length);
|
|
35
|
+
value.resize(length);
|
|
36
|
+
|
|
37
|
+
<%- if field.validator -%>
|
|
38
|
+
if (!<%= field.validator %>(value.c_str(), value.length())) {
|
|
39
|
+
std::string message = "<%= field.snake_case %> \"" + value + "\" is not supported";
|
|
40
|
+
napi_throw_error(env, nullptr, message.c_str());
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
<%- else -%>
|
|
44
|
+
if (value.length() >= HERB_PARSER_OPTIONS_STRING_CAPACITY) {
|
|
45
|
+
napi_throw_error(env, nullptr, "<%= field.snake_case %> is too long");
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
<%- end -%>
|
|
49
|
+
|
|
50
|
+
memcpy(parser_options-><%= field.c_name %>, value.c_str(), value.length() + 1);
|
|
51
|
+
}
|
|
22
52
|
<%- elsif field.nullable? -%>
|
|
23
53
|
napi_valuetype property_type;
|
|
24
54
|
napi_typeof(env, property, &property_type);
|
|
@@ -38,4 +68,6 @@ void herb_extract_parser_options(napi_env env, napi_value options, parser_option
|
|
|
38
68
|
}
|
|
39
69
|
}
|
|
40
70
|
<%- end -%>
|
|
71
|
+
|
|
72
|
+
return true;
|
|
41
73
|
}
|
|
@@ -7,6 +7,6 @@ extern "C" {
|
|
|
7
7
|
#include "../extension/libherb/include/parser/parser_options.h"
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
bool herb_extract_parser_options(napi_env env, napi_value options, parser_options_T* parser_options);
|
|
11
11
|
|
|
12
12
|
#endif
|
|
@@ -1,55 +1,21 @@
|
|
|
1
|
-
fn read_node_body(
|
|
1
|
+
fn read_node_body(
|
|
2
|
+
buffer: &mut SerializationBuffer,
|
|
3
|
+
type_id: u8,
|
|
4
|
+
pool: usize,
|
|
5
|
+
node: &mut PrismNode,
|
|
6
|
+
stack: &mut Vec<Option<PrismNode>>,
|
|
7
|
+
) {
|
|
2
8
|
match type_id {
|
|
3
9
|
<%- prism_nodes.each do |prism_node| -%>
|
|
4
10
|
<%= prism_node.type_id %> => {
|
|
5
|
-
<%- if prism_node.name == "DefNode" -%>
|
|
6
|
-
buffer.read_uint32();
|
|
7
|
-
<%- end -%>
|
|
8
|
-
|
|
9
11
|
let flags = buffer.read_var_int() as u32;
|
|
10
12
|
node.flags = flags;
|
|
11
13
|
|
|
12
14
|
<%- prism_node.fields.each do |field| -%>
|
|
13
15
|
<%- case field.type -%>
|
|
14
|
-
<%- when "node" -%>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
node.children.push(child);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
<%- if field.name == "receiver" -%>
|
|
21
|
-
node.receiver_index = Some(node.children.len() - 1);
|
|
22
|
-
<%- elsif prism_node.name == "AssocNode" && field.name == "key" -%>
|
|
23
|
-
node.key = Some(Box::new(node.children[node.children.len() - 1].clone()));
|
|
24
|
-
<%- end -%>
|
|
25
|
-
|
|
26
|
-
<%- when "node?" -%>
|
|
27
|
-
if buffer.peek_byte() != 0 {
|
|
28
|
-
let child = read_node(buffer, pool);
|
|
29
|
-
node.children.push(child);
|
|
30
|
-
<%- if field.name == "block" -%>
|
|
31
|
-
node.has_block = true;
|
|
32
|
-
<%- end -%>
|
|
33
|
-
|
|
34
|
-
<%- if field.name == "receiver" -%>
|
|
35
|
-
node.receiver_index = Some(node.children.len() - 1);
|
|
36
|
-
<%- elsif prism_node.name == "AssocNode" && field.name == "key" -%>
|
|
37
|
-
node.key = Some(Box::new(node.children[node.children.len() - 1].clone()));
|
|
38
|
-
<%- end -%>
|
|
39
|
-
|
|
40
|
-
} else {
|
|
41
|
-
buffer.read_byte();
|
|
42
|
-
}
|
|
43
|
-
<%- when "node[]" -%>
|
|
44
|
-
{
|
|
45
|
-
let count = buffer.read_var_int();
|
|
46
|
-
|
|
47
|
-
for _ in 0..count {
|
|
48
|
-
let child = read_node(buffer, pool);
|
|
49
|
-
node.children.push(child);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
16
|
+
<%- when "node", "node?" -%>
|
|
17
|
+
<%- when "node[]" -%>
|
|
18
|
+
let <%= field.name %>_count = buffer.read_var_int();
|
|
53
19
|
<%- when "string" -%>
|
|
54
20
|
<%- if field.name == "unescaped" -%>
|
|
55
21
|
node.unescaped = Some(buffer.read_string_field(flags));
|
|
@@ -93,12 +59,92 @@ fn read_node_body(buffer: &mut SerializationBuffer, type_id: u8, pool: usize, no
|
|
|
93
59
|
<%- raise "unhandled prism field type: #{field.type}" -%>
|
|
94
60
|
<%- end -%>
|
|
95
61
|
<%- end -%>
|
|
62
|
+
|
|
63
|
+
<%- prism_node.fields.reverse.each do |field| -%>
|
|
64
|
+
<%- case field.type -%>
|
|
65
|
+
<%- when "node", "node?" -%>
|
|
66
|
+
let <%= field.name %>_child = stack.pop().flatten();
|
|
67
|
+
<%- when "node[]" -%>
|
|
68
|
+
let <%= field.name %>_children = stack.split_off(stack.len().saturating_sub(<%= field.name %>_count));
|
|
69
|
+
<%- end -%>
|
|
70
|
+
<%- end -%>
|
|
71
|
+
|
|
72
|
+
<%- prism_node.fields.each do |field| -%>
|
|
73
|
+
<%- case field.type -%>
|
|
74
|
+
<%- when "node", "node?" -%>
|
|
75
|
+
if let Some(child) = <%= field.name %>_child {
|
|
76
|
+
node.children.push(child);
|
|
77
|
+
<%- if field.name == "block" && field.type == "node?" -%>
|
|
78
|
+
node.has_block = true;
|
|
79
|
+
<%- end -%>
|
|
80
|
+
<%- if field.name == "receiver" -%>
|
|
81
|
+
node.receiver_index = Some(node.children.len() - 1);
|
|
82
|
+
<%- elsif prism_node.name == "AssocNode" && field.name == "key" -%>
|
|
83
|
+
node.key = Some(Box::new(node.children[node.children.len() - 1].clone()));
|
|
84
|
+
<%- end -%>
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
<%- when "node[]" -%>
|
|
88
|
+
node.children.extend(<%= field.name %>_children.into_iter().flatten());
|
|
89
|
+
|
|
90
|
+
<%- end -%>
|
|
91
|
+
<%- end -%>
|
|
96
92
|
}
|
|
97
93
|
<%- end -%>
|
|
98
94
|
_ => {}
|
|
99
95
|
}
|
|
100
96
|
}
|
|
101
97
|
|
|
98
|
+
fn record_child_count(buffer: &mut SerializationBuffer, type_id: u8, pool: usize) -> usize {
|
|
99
|
+
#[allow(unused_mut)]
|
|
100
|
+
let mut count = 0;
|
|
101
|
+
|
|
102
|
+
match type_id {
|
|
103
|
+
<%- prism_nodes.each do |prism_node| -%>
|
|
104
|
+
<%= prism_node.type_id %> => {
|
|
105
|
+
buffer.read_var_int();
|
|
106
|
+
|
|
107
|
+
<%- prism_node.fields.each do |field| -%>
|
|
108
|
+
<%- case field.type -%>
|
|
109
|
+
<%- when "node", "node?" -%>
|
|
110
|
+
count += 1;
|
|
111
|
+
<%- when "node[]" -%>
|
|
112
|
+
count += buffer.read_var_int();
|
|
113
|
+
<%- when "string" -%>
|
|
114
|
+
buffer.read_string_field(0);
|
|
115
|
+
<%- when "constant" -%>
|
|
116
|
+
buffer.read_required_constant(pool);
|
|
117
|
+
<%- when "constant?" -%>
|
|
118
|
+
buffer.read_optional_constant(pool);
|
|
119
|
+
<%- when "constant[]" -%>
|
|
120
|
+
for _ in 0..buffer.read_var_int() {
|
|
121
|
+
buffer.read_required_constant(pool);
|
|
122
|
+
}
|
|
123
|
+
<%- when "location" -%>
|
|
124
|
+
buffer.read_location();
|
|
125
|
+
<%- when "location?" -%>
|
|
126
|
+
buffer.read_optional_location();
|
|
127
|
+
<%- when "uint8" -%>
|
|
128
|
+
buffer.read_byte();
|
|
129
|
+
<%- when "uint32" -%>
|
|
130
|
+
buffer.read_var_int();
|
|
131
|
+
<%- when "integer" -%>
|
|
132
|
+
buffer.read_integer();
|
|
133
|
+
<%- when "double" -%>
|
|
134
|
+
buffer.read_double();
|
|
135
|
+
<%- when "flags" -%>
|
|
136
|
+
<%- else -%>
|
|
137
|
+
<%- raise "unhandled prism field type: #{field.type}" -%>
|
|
138
|
+
<%- end -%>
|
|
139
|
+
<%- end -%>
|
|
140
|
+
}
|
|
141
|
+
<%- end -%>
|
|
142
|
+
_ => {}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
count
|
|
146
|
+
}
|
|
147
|
+
|
|
102
148
|
fn node_type_name_for(type_id: u8) -> String {
|
|
103
149
|
match type_id {
|
|
104
150
|
<%- prism_nodes.each do |prism_node| -%>
|
|
@@ -8,14 +8,12 @@ fn prettyprint_body(
|
|
|
8
8
|
start_offset: usize,
|
|
9
9
|
end_offset: usize,
|
|
10
10
|
newlines: &[usize],
|
|
11
|
+
children: &mut std::vec::IntoIter<Option<PrismRecord>>,
|
|
11
12
|
) {
|
|
12
13
|
match type_id {
|
|
13
14
|
<%- prism_nodes.each do |prism_node| -%>
|
|
14
15
|
<%- entries = prism_node.entries -%>
|
|
15
16
|
<%= prism_node.type_id %> => {
|
|
16
|
-
<%- if prism_node.name == "DefNode" -%>
|
|
17
|
-
buffer.read_uint32();
|
|
18
|
-
<%- end -%>
|
|
19
17
|
#[allow(unused_variables)]
|
|
20
18
|
let flags = buffer.read_var_int() as u32;
|
|
21
19
|
output.push_str(&format!("@ <%= prism_node.name %> (location: {})\n", location_string(start_offset, end_offset, newlines)));
|
|
@@ -45,29 +43,18 @@ fn prettyprint_body(
|
|
|
45
43
|
|
|
46
44
|
output.push('\n');
|
|
47
45
|
}
|
|
48
|
-
<%- when "node" -%>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if buffer.peek_byte() == 0 {
|
|
61
|
-
buffer.read_byte();
|
|
62
|
-
output.push_str(" nil\n");
|
|
63
|
-
} else {
|
|
64
|
-
output.push('\n');
|
|
65
|
-
let saved = prefix.len();
|
|
66
|
-
prefix.push_str("<%= preadd %>");
|
|
67
|
-
let copy = prefix.clone();
|
|
68
|
-
output.push_str(©);
|
|
69
|
-
prettyprint_node(buffer, pool, output, prefix, newlines);
|
|
70
|
-
prefix.truncate(saved);
|
|
46
|
+
<%- when "node", "node?" -%>
|
|
47
|
+
match children.next().flatten() {
|
|
48
|
+
None => output.push_str(" nil\n"),
|
|
49
|
+
Some(child) => {
|
|
50
|
+
output.push('\n');
|
|
51
|
+
let saved = prefix.len();
|
|
52
|
+
prefix.push_str("<%= preadd %>");
|
|
53
|
+
let copy = prefix.clone();
|
|
54
|
+
output.push_str(©);
|
|
55
|
+
prettyprint_record(child, buffer, pool, output, prefix, newlines);
|
|
56
|
+
prefix.truncate(saved);
|
|
57
|
+
}
|
|
71
58
|
}
|
|
72
59
|
<%- when "node[]" -%>
|
|
73
60
|
{
|
|
@@ -81,7 +68,11 @@ fn prettyprint_body(
|
|
|
81
68
|
output.push_str(©);
|
|
82
69
|
output.push_str("+-- ");
|
|
83
70
|
prefix.push_str(if index == count - 1 { " " } else { "| " });
|
|
84
|
-
|
|
71
|
+
|
|
72
|
+
if let Some(child) = children.next().flatten() {
|
|
73
|
+
prettyprint_record(child, buffer, pool, output, prefix, newlines);
|
|
74
|
+
}
|
|
75
|
+
|
|
85
76
|
prefix.truncate(saved);
|
|
86
77
|
}
|
|
87
78
|
}
|