diff --git a/bin/force_update_snapshots b/bin/force_update_snapshots index 33666760a..69f4b40cf 100755 --- a/bin/force_update_snapshots +++ b/bin/force_update_snapshots @@ -2,7 +2,7 @@ set -e # Exit on error -FORCE_UPDATE_SNAPSHOTS=true bundle exec rake test +FORCE_UPDATE_SNAPSHOTS=true bundle exec rake test:all echo "" echo "Force updated snapshots!" diff --git a/config.yml b/config.yml index 9718ca6d8..2363d9a77 100644 --- a/config.yml +++ b/config.yml @@ -164,7 +164,7 @@ errors: - name: ERBCaseWithConditionsError message: - template: "A `case` statement with `when`/`in` in a single ERB tag cannot be formatted. Use separate tags for `case` and its conditions." + template: "A `case` statement with `when`/`in` conditions in a single ERB tag cannot be reliably parsed, compiled, and formatted. Use separate ERB tags for `case` and its conditions (e.g., `<% case x %>` followed by `<% when y %>`)." arguments: [] fields: [] diff --git a/lib/herb/engine/compiler.rb b/lib/herb/engine/compiler.rb index 818f96a3b..6d47d1790 100644 --- a/lib/herb/engine/compiler.rb +++ b/lib/herb/engine/compiler.rb @@ -194,7 +194,9 @@ def visit_erb_content_node(node) end def visit_erb_control_node(node, &_block) - apply_trim(node, node.content.value.strip) + if node.content + apply_trim(node, node.content.value.strip) + end yield if block_given? end diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 7880640e8..0dd761e1c 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -57,6 +57,8 @@ static analyzed_ruby_T* herb_analyze_ruby(hb_string_T source) { } static bool analyze_erb_content(const AST_NODE_T* node, void* data) { + const parser_options_T* options = (const parser_options_T*) data; + if (node->type == AST_ERB_CONTENT_NODE) { AST_ERB_CONTENT_NODE_T* erb_content_node = (AST_ERB_CONTENT_NODE_T*) node; @@ -78,9 +80,7 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) { ); } - if (!analyzed->valid - && ((analyzed->case_node_count > 0 && analyzed->when_node_count > 0) - || (analyzed->case_match_node_count > 0 && analyzed->in_node_count > 0))) { + if (options && options->strict && !analyzed->valid && has_inline_case_condition(analyzed)) { append_erb_case_with_conditions_error( erb_content_node->base.location.start, erb_content_node->base.location.end, @@ -279,6 +279,10 @@ static size_t process_case_structure( hb_array_T* in_conditions = hb_array_init(8); hb_array_T* non_when_non_in_children = hb_array_init(8); + analyzed_ruby_T* analyzed = erb_node->analyzed_ruby; + bool has_inline_when = has_case_node(analyzed) && has_when_node(analyzed); + bool has_inline_in = has_case_match_node(analyzed) && has_in_node(analyzed); + index++; const control_type_t prelude_stop[] = { CONTROL_TYPE_WHEN, CONTROL_TYPE_IN, CONTROL_TYPE_END }; @@ -290,6 +294,33 @@ static size_t process_case_structure( sizeof(prelude_stop) / sizeof(prelude_stop[0]) ); + // Create a synthetic when/in node for inline when/in (e.g., <% case variable when "a" %>), + if (has_inline_when || has_inline_in) { + hb_array_T* statements = non_when_non_in_children; + non_when_non_in_children = hb_array_init(8); + + position_T start_position = + erb_node->tag_closing ? erb_node->tag_closing->location.end : erb_node->content->location.end; + position_T end_position = start_position; + + if (hb_array_size(statements) > 0) { + AST_NODE_T* last_child = hb_array_last(statements); + end_position = last_child->location.end; + } + + if (has_inline_when) { + AST_NODE_T* synthetic_node = (AST_NODE_T*) + ast_erb_when_node_init(NULL, NULL, NULL, NULL, statements, start_position, end_position, hb_array_init(0)); + + hb_array_append(when_conditions, synthetic_node); + } else { + AST_NODE_T* synthetic_node = (AST_NODE_T*) + ast_erb_in_node_init(NULL, NULL, NULL, NULL, statements, start_position, end_position, hb_array_init(0)); + + hb_array_append(in_conditions, synthetic_node); + } + } + while (index < hb_array_size(array)) { AST_ERB_CONTENT_NODE_T* next_erb = get_erb_content_at(array, index); @@ -754,8 +785,8 @@ hb_array_T* rewrite_node_array(AST_NODE_T* node, hb_array_T* array, analyze_ruby return new_array; } -void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source, bool strict) { - herb_visit_node((AST_NODE_T*) document, analyze_erb_content, NULL); +void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source, const parser_options_T* options) { + herb_visit_node((AST_NODE_T*) document, analyze_erb_content, (void*) options); analyze_ruby_context_T* context = malloc(sizeof(analyze_ruby_context_T)); @@ -784,7 +815,7 @@ void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source, herb_analyze_parse_errors(document, source); - herb_parser_match_html_tags_post_analyze(document, strict); + herb_parser_match_html_tags_post_analyze(document, options); hb_array_free(&context->ruby_context_stack); diff --git a/src/analyze/helpers.c b/src/analyze/helpers.c index e75d35f29..1cb8d44a2 100644 --- a/src/analyze/helpers.c +++ b/src/analyze/helpers.c @@ -6,79 +6,84 @@ #include "../include/util/string.h" bool has_if_node(analyzed_ruby_T* analyzed) { - return analyzed->if_node_count > 0; + return analyzed && analyzed->if_node_count > 0; } bool has_elsif_node(analyzed_ruby_T* analyzed) { - return analyzed->elsif_node_count > 0; + return analyzed && analyzed->elsif_node_count > 0; } bool has_else_node(analyzed_ruby_T* analyzed) { - return analyzed->else_node_count > 0; + return analyzed && analyzed->else_node_count > 0; } bool has_end(analyzed_ruby_T* analyzed) { - return analyzed->end_count > 0; + return analyzed && analyzed->end_count > 0; } bool has_block_node(analyzed_ruby_T* analyzed) { - return analyzed->block_node_count > 0; + return analyzed && analyzed->block_node_count > 0; } bool has_block_closing(analyzed_ruby_T* analyzed) { - return analyzed->block_closing_count > 0; + return analyzed && analyzed->block_closing_count > 0; } bool has_case_node(analyzed_ruby_T* analyzed) { - return analyzed->case_node_count > 0; + return analyzed && analyzed->case_node_count > 0; } bool has_case_match_node(analyzed_ruby_T* analyzed) { - return analyzed->case_match_node_count > 0; + return analyzed && analyzed->case_match_node_count > 0; } bool has_when_node(analyzed_ruby_T* analyzed) { - return analyzed->when_node_count > 0; + return analyzed && analyzed->when_node_count > 0; } bool has_in_node(analyzed_ruby_T* analyzed) { - return analyzed->in_node_count > 0; + return analyzed && analyzed->in_node_count > 0; } bool has_for_node(analyzed_ruby_T* analyzed) { - return analyzed->for_node_count > 0; + return analyzed && analyzed->for_node_count > 0; } bool has_while_node(analyzed_ruby_T* analyzed) { - return analyzed->while_node_count > 0; + return analyzed && analyzed->while_node_count > 0; } bool has_until_node(analyzed_ruby_T* analyzed) { - return analyzed->until_node_count > 0; + return analyzed && analyzed->until_node_count > 0; } bool has_begin_node(analyzed_ruby_T* analyzed) { - return analyzed->begin_node_count > 0; + return analyzed && analyzed->begin_node_count > 0; } bool has_rescue_node(analyzed_ruby_T* analyzed) { - return analyzed->rescue_node_count > 0; + return analyzed && analyzed->rescue_node_count > 0; } bool has_ensure_node(analyzed_ruby_T* analyzed) { - return analyzed->ensure_node_count > 0; + return analyzed && analyzed->ensure_node_count > 0; } bool has_unless_node(analyzed_ruby_T* analyzed) { - return analyzed->unless_node_count > 0; + return analyzed && analyzed->unless_node_count > 0; } bool has_yield_node(analyzed_ruby_T* analyzed) { - return analyzed->yield_node_count > 0; + return analyzed && analyzed->yield_node_count > 0; } bool has_then_keyword(analyzed_ruby_T* analyzed) { - return analyzed->then_keyword_count > 0; + return analyzed && analyzed->then_keyword_count > 0; +} + +bool has_inline_case_condition(analyzed_ruby_T* analyzed) { + return (has_case_node(analyzed) && has_when_node(analyzed)) + || (has_case_match_node(analyzed) && has_in_node(analyzed)); } bool has_error_message(analyzed_ruby_T* analyzed, const char* message) { diff --git a/src/herb.c b/src/herb.c index ad2b7e78e..0edc94cfc 100644 --- a/src/herb.c +++ b/src/herb.c @@ -44,7 +44,7 @@ HERB_EXPORTED_FUNCTION AST_DOCUMENT_NODE_T* herb_parse(const char* source, const herb_parser_deinit(&parser); - if (parser_options.analyze) { herb_analyze_parse_tree(document, source, parser_options.strict); } + if (parser_options.analyze) { herb_analyze_parse_tree(document, source, &parser_options); } return document; } diff --git a/src/include/analyze/analyze.h b/src/include/analyze/analyze.h index 12e961718..6cda94f11 100644 --- a/src/include/analyze/analyze.h +++ b/src/include/analyze/analyze.h @@ -3,6 +3,7 @@ #include "analyzed_ruby.h" #include "../ast_nodes.h" +#include "../parser.h" #include "../util/hb_array.h" typedef struct ANALYZE_RUBY_CONTEXT_STRUCT { @@ -39,7 +40,7 @@ typedef struct { } invalid_erb_context_T; void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source); -void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source, bool strict); +void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source, const parser_options_T* options); hb_array_T* rewrite_node_array(AST_NODE_T* node, hb_array_T* array, analyze_ruby_context_T* context); bool transform_erb_nodes(const AST_NODE_T* node, void* data); diff --git a/src/include/analyze/helpers.h b/src/include/analyze/helpers.h index a815d93ec..6443015ff 100644 --- a/src/include/analyze/helpers.h +++ b/src/include/analyze/helpers.h @@ -26,6 +26,7 @@ bool has_ensure_node(analyzed_ruby_T* analyzed); bool has_unless_node(analyzed_ruby_T* analyzed); bool has_yield_node(analyzed_ruby_T* analyzed); bool has_then_keyword(analyzed_ruby_T* analyzed); +bool has_inline_case_condition(analyzed_ruby_T* analyzed); bool has_error_message(analyzed_ruby_T* anlayzed, const char* message); diff --git a/src/include/parser.h b/src/include/parser.h index 81b34d8d2..6ac11f05f 100644 --- a/src/include/parser.h +++ b/src/include/parser.h @@ -23,7 +23,7 @@ typedef struct PARSER_OPTIONS_STRUCT { typedef struct MATCH_TAGS_CONTEXT_STRUCT { hb_array_T* errors; - bool strict; + const parser_options_T* options; } match_tags_context_T; extern const parser_options_T HERB_DEFAULT_PARSER_OPTIONS; @@ -45,10 +45,10 @@ void herb_parser_init(parser_T* parser, lexer_T* lexer, parser_options_T options AST_DOCUMENT_NODE_T* herb_parser_parse(parser_T* parser); -void herb_parser_match_html_tags_post_analyze(AST_DOCUMENT_NODE_T* document, bool strict); +void herb_parser_match_html_tags_post_analyze(AST_DOCUMENT_NODE_T* document, const parser_options_T* options); void herb_parser_deinit(parser_T* parser); -void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors, bool strict); +void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors, const parser_options_T* options); bool match_tags_visitor(const AST_NODE_T* node, void* data); #endif diff --git a/src/parser.c b/src/parser.c index f82b355a3..f27f9e606 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1536,9 +1536,18 @@ static size_t find_implicit_close_index(hb_array_T* nodes, size_t start_idx, hb_ return hb_array_size(nodes); } -static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T* errors, bool strict); - -static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T* errors, bool strict) { +static hb_array_T* parser_build_elements_from_tags( + hb_array_T* nodes, + hb_array_T* errors, + const parser_options_T* options +); + +static hb_array_T* parser_build_elements_from_tags( + hb_array_T* nodes, + hb_array_T* errors, + const parser_options_T* options +) { + bool strict = options ? options->strict : false; hb_array_T* result = hb_array_init(hb_array_size(nodes)); for (size_t index = 0; index < hb_array_size(nodes); index++) { @@ -1561,7 +1570,7 @@ static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T hb_array_append(body, hb_array_get(nodes, j)); } - hb_array_T* processed_body = parser_build_elements_from_tags(body, errors, strict); + hb_array_T* processed_body = parser_build_elements_from_tags(body, errors, options); hb_array_free(&body); position_T end_position = open_tag->base.location.end; @@ -1622,7 +1631,7 @@ static hb_array_T* parser_build_elements_from_tags(hb_array_T* nodes, hb_array_T hb_array_append(body, hb_array_get(nodes, j)); } - hb_array_T* processed_body = parser_build_elements_from_tags(body, errors, strict); + hb_array_T* processed_body = parser_build_elements_from_tags(body, errors, options); hb_array_free(&body); hb_array_T* element_errors = hb_array_init(8); @@ -1728,10 +1737,10 @@ void herb_parser_deinit(parser_T* parser) { } } -void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors, bool strict) { +void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors, const parser_options_T* options) { if (nodes == NULL || hb_array_size(nodes) == 0) { return; } - hb_array_T* processed = parser_build_elements_from_tags(nodes, errors, strict); + hb_array_T* processed = parser_build_elements_from_tags(nodes, errors, options); nodes->size = 0; @@ -1741,7 +1750,7 @@ void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors, bool strict hb_array_free(&processed); - match_tags_context_T context = { .errors = errors, .strict = strict }; + match_tags_context_T context = { .errors = errors, .options = options }; for (size_t i = 0; i < hb_array_size(nodes); i++) { AST_NODE_T* node = (AST_NODE_T*) hb_array_get(nodes, i); @@ -1751,8 +1760,8 @@ void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors, bool strict } } -void herb_parser_match_html_tags_post_analyze(AST_DOCUMENT_NODE_T* document, bool strict) { +void herb_parser_match_html_tags_post_analyze(AST_DOCUMENT_NODE_T* document, const parser_options_T* options) { if (document == NULL) { return; } - match_tags_in_node_array(document->children, document->base.errors, strict); + match_tags_in_node_array(document->children, document->base.errors, options); } diff --git a/templates/src/parser_match_tags.c.erb b/templates/src/parser_match_tags.c.erb index 237d98949..27184bab1 100644 --- a/templates/src/parser_match_tags.c.erb +++ b/templates/src/parser_match_tags.c.erb @@ -25,7 +25,7 @@ bool match_tags_visitor(const AST_NODE_T* node, void* data) { <%- array_fields.each do |field| -%> if (<%= node.human %>-><%= field.name %> != NULL) { - match_tags_in_node_array(<%= node.human %>-><%= field.name %>, context->errors, context->strict); + match_tags_in_node_array(<%= node.human %>-><%= field.name %>, context->errors, context->options); } <%- end -%> <%- single_node_fields.each do |field| -%> diff --git a/test/engine/evaluation/case_test.rb b/test/engine/evaluation/case_test.rb new file mode 100644 index 000000000..4986c1483 --- /dev/null +++ b/test/engine/evaluation/case_test.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +require_relative "../../test_helper" +require_relative "../../snapshot_utils" +require_relative "../../../lib/herb/engine" + +module Engine + class CaseTest < Minitest::Spec + include SnapshotUtils + + test "case when in same ERB tag" do + template = <<~ERB + <% case status when "pending" %> + Pending + <% when "approved" %> + Approved + <% else %> + Unknown + <% end %> + ERB + + error = assert_raises(Herb::Engine::CompilationError) do + Herb::Engine.new(template, strict: true) + end + + assert_includes error.message, "ERBCaseWithConditions" + + assert_evaluated_snapshot(template, { status: "pending" }, { escape: false, strict: false }) + assert_evaluated_snapshot(template, { status: "approved" }, { escape: false, strict: false }) + assert_evaluated_snapshot(template, { status: "other" }, { escape: false, strict: false }) + end + + test "case in pattern in same ERB tag" do + template = <<~ERB + <% case count in 1 %> + One + <% in 2 %> + Two + <% else %> + Other + <% end %> + ERB + + error = assert_raises(Herb::Engine::CompilationError) do + Herb::Engine.new(template, strict: true) + end + + assert_includes error.message, "ERBCaseWithConditions" + end + + test "case when on newline in same ERB tag" do + template = <<~ERB + <% case status + when "pending" %> + Pending + <% when "approved" %> + Approved + <% end %> + ERB + + error = assert_raises(Herb::Engine::CompilationError) do + Herb::Engine.new(template, strict: true) + end + + assert_includes error.message, "ERBCaseWithConditions" + + assert_evaluated_snapshot(template, { status: "pending" }, { escape: false, strict: false }) + assert_evaluated_snapshot(template, { status: "approved" }, { escape: false, strict: false }) + end + + test "case in on newline in same ERB tag" do + template = <<~ERB + <% case count + in 1 %> + One + <% in 2 %> + Two + <% end %> + ERB + + error = assert_raises(Herb::Engine::CompilationError) do + Herb::Engine.new(template, strict: true) + end + + assert_includes error.message, "ERBCaseWithConditions" + + assert_evaluated_snapshot(template, { count: 1 }, { escape: false, strict: false }) + assert_evaluated_snapshot(template, { count: 2 }, { escape: false, strict: false }) + end + end +end diff --git a/test/engine/evaluation/heredoc_test.rb b/test/engine/evaluation/heredoc_test.rb new file mode 100644 index 000000000..39163ae13 --- /dev/null +++ b/test/engine/evaluation/heredoc_test.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require_relative "../../test_helper" +require_relative "../../snapshot_utils" +require_relative "../../../lib/herb/engine" + +module Engine + class HeredocTest < Minitest::Spec + include SnapshotUtils + + test "heredoc in code tag" do + template = <<~ERB + <% + text = <<~TEXT + Hello, world! + TEXT + %> + <%= text %> + ERB + + assert_evaluated_snapshot(template, {}, { escape: false }) + end + end +end diff --git a/test/engine/evaluation_test.rb b/test/engine/evaluation_test.rb index ed75e1391..d5a4c858b 100644 --- a/test/engine/evaluation_test.rb +++ b/test/engine/evaluation_test.rb @@ -484,18 +484,5 @@ class EvaluationTest < Minitest::Spec assert_evaluated_snapshot(template, { some_condition: false }, { escape: false }) end - - test "heredoc in code tag" do - template = <<~ERB - <% - text = <<~TEXT - Hello, world! - TEXT - %> - <%= text %> - ERB - - assert_evaluated_snapshot(template, {}, { escape: false }) - end end end diff --git a/test/parser/multiple_control_flow_test.rb b/test/parser/multiple_control_flow_test.rb index c4914bbc8..97c9cb2aa 100644 --- a/test/parser/multiple_control_flow_test.rb +++ b/test/parser/multiple_control_flow_test.rb @@ -363,23 +363,57 @@ class MultipleControlFlowTest < Minitest::Spec end test "case and when in same ERB tag" do - assert_parsed_snapshot(<<~ERB) + template = <<~ERB <% case variable when "a" %> A <% when "b" %> B <% end %> ERB + + assert_parsed_snapshot(template, strict: true) + assert_parsed_snapshot(template, strict: false) end test "case in pattern in same ERB tag" do - assert_parsed_snapshot(<<~ERB) + template = <<~ERB <% case value in 1 %> One <% in 2 %> Two <% end %> ERB + + assert_parsed_snapshot(template, strict: true) + assert_parsed_snapshot(template, strict: false) + end + + test "case and when on newline in same ERB tag" do + template = <<~ERB + <% case variable + when "a" %> + A + <% when "b" %> + B + <% end %> + ERB + + assert_parsed_snapshot(template, strict: true) + assert_parsed_snapshot(template, strict: false) + end + + test "case in pattern on newline in same ERB tag" do + template = <<~ERB + <% case value + in 1 %> + One + <% in 2 %> + Two + <% end %> + ERB + + assert_parsed_snapshot(template, strict: true) + assert_parsed_snapshot(template, strict: false) end end end diff --git a/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_23aed430da2e0530eba76d6ff44d4f48.txt b/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_23aed430da2e0530eba76d6ff44d4f48.txt new file mode 100644 index 000000000..5b0b0a5a2 --- /dev/null +++ b/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_23aed430da2e0530eba76d6ff44d4f48.txt @@ -0,0 +1,5 @@ +--- +source: "Engine::CaseTest#test_0001_case when in same ERB tag" +input: "{source: \"<% case status when \\\"pending\\\" %>\\n Pending\\n<% when \\\"approved\\\" %>\\n Approved\\n<% else %>\\n Unknown\\n<% end %>\\n\", locals: {status: \"pending\"}, options: {escape: false, strict: false}}" +--- + Pending diff --git a/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_6ca15c3a9293976c06d3d4e1421980f9.txt b/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_6ca15c3a9293976c06d3d4e1421980f9.txt new file mode 100644 index 000000000..6a98a89c3 --- /dev/null +++ b/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_6ca15c3a9293976c06d3d4e1421980f9.txt @@ -0,0 +1,5 @@ +--- +source: "Engine::CaseTest#test_0001_case when in same ERB tag" +input: "{source: \"<% case status when \\\"pending\\\" %>\\n Pending\\n<% when \\\"approved\\\" %>\\n Approved\\n<% else %>\\n Unknown\\n<% end %>\\n\", locals: {status: \"approved\"}, options: {escape: false, strict: false}}" +--- + Approved diff --git a/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_9b671780f0459813359368a1df6afaff.txt b/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_9b671780f0459813359368a1df6afaff.txt new file mode 100644 index 000000000..8d21f45c0 --- /dev/null +++ b/test/snapshots/engine/case_test/test_0001_case_when_in_same_ERB_tag_9b671780f0459813359368a1df6afaff.txt @@ -0,0 +1,5 @@ +--- +source: "Engine::CaseTest#test_0001_case when in same ERB tag" +input: "{source: \"<% case status when \\\"pending\\\" %>\\n Pending\\n<% when \\\"approved\\\" %>\\n Approved\\n<% else %>\\n Unknown\\n<% end %>\\n\", locals: {status: \"other\"}, options: {escape: false, strict: false}}" +--- + Unknown diff --git a/test/snapshots/engine/case_test/test_0003_case_when_on_newline_in_same_ERB_tag_811ef7173169870133e367deaede4fe4.txt b/test/snapshots/engine/case_test/test_0003_case_when_on_newline_in_same_ERB_tag_811ef7173169870133e367deaede4fe4.txt new file mode 100644 index 000000000..9a3f716dd --- /dev/null +++ b/test/snapshots/engine/case_test/test_0003_case_when_on_newline_in_same_ERB_tag_811ef7173169870133e367deaede4fe4.txt @@ -0,0 +1,5 @@ +--- +source: "Engine::CaseTest#test_0003_case when on newline in same ERB tag" +input: "{source: \"<% case status\\n when \\\"pending\\\" %>\\n Pending\\n<% when \\\"approved\\\" %>\\n Approved\\n<% end %>\\n\", locals: {status: \"approved\"}, options: {escape: false, strict: false}}" +--- + Approved diff --git a/test/snapshots/engine/case_test/test_0003_case_when_on_newline_in_same_ERB_tag_ab777e9f2c3de2a5939a0bc885c8d74c.txt b/test/snapshots/engine/case_test/test_0003_case_when_on_newline_in_same_ERB_tag_ab777e9f2c3de2a5939a0bc885c8d74c.txt new file mode 100644 index 000000000..1bbfc8c06 --- /dev/null +++ b/test/snapshots/engine/case_test/test_0003_case_when_on_newline_in_same_ERB_tag_ab777e9f2c3de2a5939a0bc885c8d74c.txt @@ -0,0 +1,5 @@ +--- +source: "Engine::CaseTest#test_0003_case when on newline in same ERB tag" +input: "{source: \"<% case status\\n when \\\"pending\\\" %>\\n Pending\\n<% when \\\"approved\\\" %>\\n Approved\\n<% end %>\\n\", locals: {status: \"pending\"}, options: {escape: false, strict: false}}" +--- + Pending diff --git a/test/snapshots/engine/case_test/test_0004_case_in_on_newline_in_same_ERB_tag_0a592ed5a885b7022e49432c323b8991.txt b/test/snapshots/engine/case_test/test_0004_case_in_on_newline_in_same_ERB_tag_0a592ed5a885b7022e49432c323b8991.txt new file mode 100644 index 000000000..21efc17c5 --- /dev/null +++ b/test/snapshots/engine/case_test/test_0004_case_in_on_newline_in_same_ERB_tag_0a592ed5a885b7022e49432c323b8991.txt @@ -0,0 +1,5 @@ +--- +source: "Engine::CaseTest#test_0004_case in on newline in same ERB tag" +input: "{source: \"<% case count\\n in 1 %>\\n One\\n<% in 2 %>\\n Two\\n<% end %>\\n\", locals: {count: 1}, options: {escape: false, strict: false}}" +--- + One diff --git a/test/snapshots/engine/case_test/test_0004_case_in_on_newline_in_same_ERB_tag_efdcbb5c5c9196a57d4695520c828efc.txt b/test/snapshots/engine/case_test/test_0004_case_in_on_newline_in_same_ERB_tag_efdcbb5c5c9196a57d4695520c828efc.txt new file mode 100644 index 000000000..90ab63bea --- /dev/null +++ b/test/snapshots/engine/case_test/test_0004_case_in_on_newline_in_same_ERB_tag_efdcbb5c5c9196a57d4695520c828efc.txt @@ -0,0 +1,5 @@ +--- +source: "Engine::CaseTest#test_0004_case in on newline in same ERB tag" +input: "{source: \"<% case count\\n in 1 %>\\n One\\n<% in 2 %>\\n Two\\n<% end %>\\n\", locals: {count: 2}, options: {escape: false, strict: false}}" +--- + Two diff --git a/test/snapshots/engine/evaluation_test/test_0039_heredoc_in_code_tag_89436ef132cfca5077afe91beb8082b8.txt b/test/snapshots/engine/heredoc_test/test_0001_heredoc_in_code_tag_89436ef132cfca5077afe91beb8082b8.txt similarity index 71% rename from test/snapshots/engine/evaluation_test/test_0039_heredoc_in_code_tag_89436ef132cfca5077afe91beb8082b8.txt rename to test/snapshots/engine/heredoc_test/test_0001_heredoc_in_code_tag_89436ef132cfca5077afe91beb8082b8.txt index fed1e294b..0147d18fe 100644 --- a/test/snapshots/engine/evaluation_test/test_0039_heredoc_in_code_tag_89436ef132cfca5077afe91beb8082b8.txt +++ b/test/snapshots/engine/heredoc_test/test_0001_heredoc_in_code_tag_89436ef132cfca5077afe91beb8082b8.txt @@ -1,5 +1,5 @@ --- -source: "Engine::EvaluationTest#test_0039_heredoc in code tag" +source: "Engine::HeredocTest#test_0001_heredoc in code tag" input: "{source: \"<%\\n text = <<~TEXT\\n Hello, world!\\n TEXT\\n%>\\n<%= text %>\\n\", locals: {}, options: {escape: false}}" --- Hello, world! diff --git a/test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba-08996694f7ff1e6e34277dc32f646630.txt b/test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba-08996694f7ff1e6e34277dc32f646630.txt new file mode 100644 index 000000000..09584cd75 --- /dev/null +++ b/test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba-08996694f7ff1e6e34277dc32f646630.txt @@ -0,0 +1,52 @@ +--- +source: "Parser::MultipleControlFlowTest#test_0041_case and when in same ERB tag" +input: |2- +<% case variable when "a" %> + A +<% when "b" %> + B +<% end %> +options: {strict: true} +--- +@ DocumentNode (location: (1:0)-(6:0)) +└── children: (2 items) + ├── @ ERBCaseNode (location: (1:0)-(5:9)) + │ ├── errors: (1 error) + │ │ └── @ ERBCaseWithConditionsError (location: (1:0)-(1:28)) + │ │ └── message: "A `case` statement with `when`/`in` conditions in a single ERB tag cannot be reliably parsed, compiled, and formatted. Use separate ERB tags for `case` and its conditions (e.g., `<% case x %>` followed by `<% when y %>`)." + │ │ + │ ├── tag_opening: "<%" (location: (1:0)-(1:2)) + │ ├── content: " case variable when "a" " (location: (1:2)-(1:26)) + │ ├── tag_closing: "%>" (location: (1:26)-(1:28)) + │ ├── children: [] + │ ├── conditions: (2 items) + │ │ ├── @ ERBWhenNode (location: (1:28)-(3:0)) + │ │ │ ├── tag_opening: ∅ + │ │ │ ├── content: ∅ + │ │ │ ├── tag_closing: ∅ + │ │ │ ├── then_keyword: ∅ + │ │ │ └── statements: (1 item) + │ │ │ └── @ HTMLTextNode (location: (1:28)-(3:0)) + │ │ │ └── content: "\n A\n" + │ │ │ + │ │ │ + │ │ └── @ ERBWhenNode (location: (3:0)-(3:14)) + │ │ ├── tag_opening: "<%" (location: (3:0)-(3:2)) + │ │ ├── content: " when "b" " (location: (3:2)-(3:12)) + │ │ ├── tag_closing: "%>" (location: (3:12)-(3:14)) + │ │ ├── then_keyword: ∅ + │ │ └── statements: (1 item) + │ │ └── @ HTMLTextNode (location: (3:14)-(5:0)) + │ │ └── content: "\n B\n" + │ │ + │ │ + │ ├── else_clause: ∅ + │ └── end_node: + │ └── @ ERBEndNode (location: (5:0)-(5:9)) + │ ├── tag_opening: "<%" (location: (5:0)-(5:2)) + │ ├── content: " end " (location: (5:2)-(5:7)) + │ └── tag_closing: "%>" (location: (5:7)-(5:9)) + │ + │ + └── @ HTMLTextNode (location: (5:9)-(6:0)) + └── content: "\n" \ No newline at end of file diff --git a/test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba.txt b/test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba-2ffd01e26b8c99a6c7a6dad67c9489dc.txt similarity index 71% rename from test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba.txt rename to test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba-2ffd01e26b8c99a6c7a6dad67c9489dc.txt index 58b9869c4..19e7e7b5c 100644 --- a/test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba.txt +++ b/test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba-2ffd01e26b8c99a6c7a6dad67c9489dc.txt @@ -6,22 +6,26 @@ input: |2- <% when "b" %> B <% end %> +options: {strict: false} --- @ DocumentNode (location: (1:0)-(6:0)) └── children: (2 items) ├── @ ERBCaseNode (location: (1:0)-(5:9)) - │ ├── errors: (1 error) - │ │ └── @ ERBCaseWithConditionsError (location: (1:0)-(1:28)) - │ │ └── message: "A `case` statement with `when`/`in` in a single ERB tag cannot be formatted. Use separate tags for `case` and its conditions." - │ │ │ ├── tag_opening: "<%" (location: (1:0)-(1:2)) │ ├── content: " case variable when "a" " (location: (1:2)-(1:26)) │ ├── tag_closing: "%>" (location: (1:26)-(1:28)) - │ ├── children: (1 item) - │ │ └── @ HTMLTextNode (location: (1:28)-(3:0)) - │ │ └── content: "\n A\n" - │ │ - │ ├── conditions: (1 item) + │ ├── children: [] + │ ├── conditions: (2 items) + │ │ ├── @ ERBWhenNode (location: (1:28)-(3:0)) + │ │ │ ├── tag_opening: ∅ + │ │ │ ├── content: ∅ + │ │ │ ├── tag_closing: ∅ + │ │ │ ├── then_keyword: ∅ + │ │ │ └── statements: (1 item) + │ │ │ └── @ HTMLTextNode (location: (1:28)-(3:0)) + │ │ │ └── content: "\n A\n" + │ │ │ + │ │ │ │ │ └── @ ERBWhenNode (location: (3:0)-(3:14)) │ │ ├── tag_opening: "<%" (location: (3:0)-(3:2)) │ │ ├── content: " when "b" " (location: (3:2)-(3:12)) diff --git a/test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966-08996694f7ff1e6e34277dc32f646630.txt b/test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966-08996694f7ff1e6e34277dc32f646630.txt new file mode 100644 index 000000000..bfdb501c4 --- /dev/null +++ b/test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966-08996694f7ff1e6e34277dc32f646630.txt @@ -0,0 +1,52 @@ +--- +source: "Parser::MultipleControlFlowTest#test_0042_case in pattern in same ERB tag" +input: |2- +<% case value in 1 %> + One +<% in 2 %> + Two +<% end %> +options: {strict: true} +--- +@ DocumentNode (location: (1:0)-(6:0)) +└── children: (2 items) + ├── @ ERBCaseMatchNode (location: (1:0)-(5:9)) + │ ├── errors: (1 error) + │ │ └── @ ERBCaseWithConditionsError (location: (1:0)-(1:21)) + │ │ └── message: "A `case` statement with `when`/`in` conditions in a single ERB tag cannot be reliably parsed, compiled, and formatted. Use separate ERB tags for `case` and its conditions (e.g., `<% case x %>` followed by `<% when y %>`)." + │ │ + │ ├── tag_opening: "<%" (location: (1:0)-(1:2)) + │ ├── content: " case value in 1 " (location: (1:2)-(1:19)) + │ ├── tag_closing: "%>" (location: (1:19)-(1:21)) + │ ├── children: [] + │ ├── conditions: (2 items) + │ │ ├── @ ERBInNode (location: (1:21)-(3:0)) + │ │ │ ├── tag_opening: ∅ + │ │ │ ├── content: ∅ + │ │ │ ├── tag_closing: ∅ + │ │ │ ├── then_keyword: ∅ + │ │ │ └── statements: (1 item) + │ │ │ └── @ HTMLTextNode (location: (1:21)-(3:0)) + │ │ │ └── content: "\n One\n" + │ │ │ + │ │ │ + │ │ └── @ ERBInNode (location: (3:0)-(3:10)) + │ │ ├── tag_opening: "<%" (location: (3:0)-(3:2)) + │ │ ├── content: " in 2 " (location: (3:2)-(3:8)) + │ │ ├── tag_closing: "%>" (location: (3:8)-(3:10)) + │ │ ├── then_keyword: ∅ + │ │ └── statements: (1 item) + │ │ └── @ HTMLTextNode (location: (3:10)-(5:0)) + │ │ └── content: "\n Two\n" + │ │ + │ │ + │ ├── else_clause: ∅ + │ └── end_node: + │ └── @ ERBEndNode (location: (5:0)-(5:9)) + │ ├── tag_opening: "<%" (location: (5:0)-(5:2)) + │ ├── content: " end " (location: (5:2)-(5:7)) + │ └── tag_closing: "%>" (location: (5:7)-(5:9)) + │ + │ + └── @ HTMLTextNode (location: (5:9)-(6:0)) + └── content: "\n" \ No newline at end of file diff --git a/test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966.txt b/test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966-2ffd01e26b8c99a6c7a6dad67c9489dc.txt similarity index 71% rename from test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966.txt rename to test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966-2ffd01e26b8c99a6c7a6dad67c9489dc.txt index a8fbbd0a2..35a6fa0d7 100644 --- a/test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966.txt +++ b/test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966-2ffd01e26b8c99a6c7a6dad67c9489dc.txt @@ -6,22 +6,26 @@ input: |2- <% in 2 %> Two <% end %> +options: {strict: false} --- @ DocumentNode (location: (1:0)-(6:0)) └── children: (2 items) ├── @ ERBCaseMatchNode (location: (1:0)-(5:9)) - │ ├── errors: (1 error) - │ │ └── @ ERBCaseWithConditionsError (location: (1:0)-(1:21)) - │ │ └── message: "A `case` statement with `when`/`in` in a single ERB tag cannot be formatted. Use separate tags for `case` and its conditions." - │ │ │ ├── tag_opening: "<%" (location: (1:0)-(1:2)) │ ├── content: " case value in 1 " (location: (1:2)-(1:19)) │ ├── tag_closing: "%>" (location: (1:19)-(1:21)) - │ ├── children: (1 item) - │ │ └── @ HTMLTextNode (location: (1:21)-(3:0)) - │ │ └── content: "\n One\n" - │ │ - │ ├── conditions: (1 item) + │ ├── children: [] + │ ├── conditions: (2 items) + │ │ ├── @ ERBInNode (location: (1:21)-(3:0)) + │ │ │ ├── tag_opening: ∅ + │ │ │ ├── content: ∅ + │ │ │ ├── tag_closing: ∅ + │ │ │ ├── then_keyword: ∅ + │ │ │ └── statements: (1 item) + │ │ │ └── @ HTMLTextNode (location: (1:21)-(3:0)) + │ │ │ └── content: "\n One\n" + │ │ │ + │ │ │ │ │ └── @ ERBInNode (location: (3:0)-(3:10)) │ │ ├── tag_opening: "<%" (location: (3:0)-(3:2)) │ │ ├── content: " in 2 " (location: (3:2)-(3:8)) diff --git a/test/snapshots/parser/multiple_control_flow_test/test_0043_case_and_when_on_newline_in_same_ERB_tag_0560399f6147186ba24ad4f6c9f5df6f-08996694f7ff1e6e34277dc32f646630.txt b/test/snapshots/parser/multiple_control_flow_test/test_0043_case_and_when_on_newline_in_same_ERB_tag_0560399f6147186ba24ad4f6c9f5df6f-08996694f7ff1e6e34277dc32f646630.txt new file mode 100644 index 000000000..58e4c32f4 --- /dev/null +++ b/test/snapshots/parser/multiple_control_flow_test/test_0043_case_and_when_on_newline_in_same_ERB_tag_0560399f6147186ba24ad4f6c9f5df6f-08996694f7ff1e6e34277dc32f646630.txt @@ -0,0 +1,54 @@ +--- +source: "Parser::MultipleControlFlowTest#test_0043_case and when on newline in same ERB tag" +input: |2- +<% case variable + when "a" %> + A +<% when "b" %> + B +<% end %> +options: {strict: true} +--- +@ DocumentNode (location: (1:0)-(7:0)) +└── children: (2 items) + ├── @ ERBCaseNode (location: (1:0)-(6:9)) + │ ├── errors: (1 error) + │ │ └── @ ERBCaseWithConditionsError (location: (1:0)-(2:14)) + │ │ └── message: "A `case` statement with `when`/`in` conditions in a single ERB tag cannot be reliably parsed, compiled, and formatted. Use separate ERB tags for `case` and its conditions (e.g., `<% case x %>` followed by `<% when y %>`)." + │ │ + │ ├── tag_opening: "<%" (location: (1:0)-(1:2)) + │ ├── content: " case variable + │ when "a" " (location: (1:2)-(2:12)) + │ ├── tag_closing: "%>" (location: (2:12)-(2:14)) + │ ├── children: [] + │ ├── conditions: (2 items) + │ │ ├── @ ERBWhenNode (location: (2:14)-(4:0)) + │ │ │ ├── tag_opening: ∅ + │ │ │ ├── content: ∅ + │ │ │ ├── tag_closing: ∅ + │ │ │ ├── then_keyword: ∅ + │ │ │ └── statements: (1 item) + │ │ │ └── @ HTMLTextNode (location: (2:14)-(4:0)) + │ │ │ └── content: "\n A\n" + │ │ │ + │ │ │ + │ │ └── @ ERBWhenNode (location: (4:0)-(4:14)) + │ │ ├── tag_opening: "<%" (location: (4:0)-(4:2)) + │ │ ├── content: " when "b" " (location: (4:2)-(4:12)) + │ │ ├── tag_closing: "%>" (location: (4:12)-(4:14)) + │ │ ├── then_keyword: ∅ + │ │ └── statements: (1 item) + │ │ └── @ HTMLTextNode (location: (4:14)-(6:0)) + │ │ └── content: "\n B\n" + │ │ + │ │ + │ ├── else_clause: ∅ + │ └── end_node: + │ └── @ ERBEndNode (location: (6:0)-(6:9)) + │ ├── tag_opening: "<%" (location: (6:0)-(6:2)) + │ ├── content: " end " (location: (6:2)-(6:7)) + │ └── tag_closing: "%>" (location: (6:7)-(6:9)) + │ + │ + └── @ HTMLTextNode (location: (6:9)-(7:0)) + └── content: "\n" \ No newline at end of file diff --git a/test/snapshots/parser/multiple_control_flow_test/test_0043_case_and_when_on_newline_in_same_ERB_tag_0560399f6147186ba24ad4f6c9f5df6f-2ffd01e26b8c99a6c7a6dad67c9489dc.txt b/test/snapshots/parser/multiple_control_flow_test/test_0043_case_and_when_on_newline_in_same_ERB_tag_0560399f6147186ba24ad4f6c9f5df6f-2ffd01e26b8c99a6c7a6dad67c9489dc.txt new file mode 100644 index 000000000..fc43443e5 --- /dev/null +++ b/test/snapshots/parser/multiple_control_flow_test/test_0043_case_and_when_on_newline_in_same_ERB_tag_0560399f6147186ba24ad4f6c9f5df6f-2ffd01e26b8c99a6c7a6dad67c9489dc.txt @@ -0,0 +1,50 @@ +--- +source: "Parser::MultipleControlFlowTest#test_0043_case and when on newline in same ERB tag" +input: |2- +<% case variable + when "a" %> + A +<% when "b" %> + B +<% end %> +options: {strict: false} +--- +@ DocumentNode (location: (1:0)-(7:0)) +└── children: (2 items) + ├── @ ERBCaseNode (location: (1:0)-(6:9)) + │ ├── tag_opening: "<%" (location: (1:0)-(1:2)) + │ ├── content: " case variable + │ when "a" " (location: (1:2)-(2:12)) + │ ├── tag_closing: "%>" (location: (2:12)-(2:14)) + │ ├── children: [] + │ ├── conditions: (2 items) + │ │ ├── @ ERBWhenNode (location: (2:14)-(4:0)) + │ │ │ ├── tag_opening: ∅ + │ │ │ ├── content: ∅ + │ │ │ ├── tag_closing: ∅ + │ │ │ ├── then_keyword: ∅ + │ │ │ └── statements: (1 item) + │ │ │ └── @ HTMLTextNode (location: (2:14)-(4:0)) + │ │ │ └── content: "\n A\n" + │ │ │ + │ │ │ + │ │ └── @ ERBWhenNode (location: (4:0)-(4:14)) + │ │ ├── tag_opening: "<%" (location: (4:0)-(4:2)) + │ │ ├── content: " when "b" " (location: (4:2)-(4:12)) + │ │ ├── tag_closing: "%>" (location: (4:12)-(4:14)) + │ │ ├── then_keyword: ∅ + │ │ └── statements: (1 item) + │ │ └── @ HTMLTextNode (location: (4:14)-(6:0)) + │ │ └── content: "\n B\n" + │ │ + │ │ + │ ├── else_clause: ∅ + │ └── end_node: + │ └── @ ERBEndNode (location: (6:0)-(6:9)) + │ ├── tag_opening: "<%" (location: (6:0)-(6:2)) + │ ├── content: " end " (location: (6:2)-(6:7)) + │ └── tag_closing: "%>" (location: (6:7)-(6:9)) + │ + │ + └── @ HTMLTextNode (location: (6:9)-(7:0)) + └── content: "\n" \ No newline at end of file diff --git a/test/snapshots/parser/multiple_control_flow_test/test_0044_case_in_pattern_on_newline_in_same_ERB_tag_469f7105ed227c9918b8e8e22644591c-08996694f7ff1e6e34277dc32f646630.txt b/test/snapshots/parser/multiple_control_flow_test/test_0044_case_in_pattern_on_newline_in_same_ERB_tag_469f7105ed227c9918b8e8e22644591c-08996694f7ff1e6e34277dc32f646630.txt new file mode 100644 index 000000000..b0595388f --- /dev/null +++ b/test/snapshots/parser/multiple_control_flow_test/test_0044_case_in_pattern_on_newline_in_same_ERB_tag_469f7105ed227c9918b8e8e22644591c-08996694f7ff1e6e34277dc32f646630.txt @@ -0,0 +1,54 @@ +--- +source: "Parser::MultipleControlFlowTest#test_0044_case in pattern on newline in same ERB tag" +input: |2- +<% case value + in 1 %> + One +<% in 2 %> + Two +<% end %> +options: {strict: true} +--- +@ DocumentNode (location: (1:0)-(7:0)) +└── children: (2 items) + ├── @ ERBCaseMatchNode (location: (1:0)-(6:9)) + │ ├── errors: (1 error) + │ │ └── @ ERBCaseWithConditionsError (location: (1:0)-(2:10)) + │ │ └── message: "A `case` statement with `when`/`in` conditions in a single ERB tag cannot be reliably parsed, compiled, and formatted. Use separate ERB tags for `case` and its conditions (e.g., `<% case x %>` followed by `<% when y %>`)." + │ │ + │ ├── tag_opening: "<%" (location: (1:0)-(1:2)) + │ ├── content: " case value + │ in 1 " (location: (1:2)-(2:8)) + │ ├── tag_closing: "%>" (location: (2:8)-(2:10)) + │ ├── children: [] + │ ├── conditions: (2 items) + │ │ ├── @ ERBInNode (location: (2:10)-(4:0)) + │ │ │ ├── tag_opening: ∅ + │ │ │ ├── content: ∅ + │ │ │ ├── tag_closing: ∅ + │ │ │ ├── then_keyword: ∅ + │ │ │ └── statements: (1 item) + │ │ │ └── @ HTMLTextNode (location: (2:10)-(4:0)) + │ │ │ └── content: "\n One\n" + │ │ │ + │ │ │ + │ │ └── @ ERBInNode (location: (4:0)-(4:10)) + │ │ ├── tag_opening: "<%" (location: (4:0)-(4:2)) + │ │ ├── content: " in 2 " (location: (4:2)-(4:8)) + │ │ ├── tag_closing: "%>" (location: (4:8)-(4:10)) + │ │ ├── then_keyword: ∅ + │ │ └── statements: (1 item) + │ │ └── @ HTMLTextNode (location: (4:10)-(6:0)) + │ │ └── content: "\n Two\n" + │ │ + │ │ + │ ├── else_clause: ∅ + │ └── end_node: + │ └── @ ERBEndNode (location: (6:0)-(6:9)) + │ ├── tag_opening: "<%" (location: (6:0)-(6:2)) + │ ├── content: " end " (location: (6:2)-(6:7)) + │ └── tag_closing: "%>" (location: (6:7)-(6:9)) + │ + │ + └── @ HTMLTextNode (location: (6:9)-(7:0)) + └── content: "\n" \ No newline at end of file diff --git a/test/snapshots/parser/multiple_control_flow_test/test_0044_case_in_pattern_on_newline_in_same_ERB_tag_469f7105ed227c9918b8e8e22644591c-2ffd01e26b8c99a6c7a6dad67c9489dc.txt b/test/snapshots/parser/multiple_control_flow_test/test_0044_case_in_pattern_on_newline_in_same_ERB_tag_469f7105ed227c9918b8e8e22644591c-2ffd01e26b8c99a6c7a6dad67c9489dc.txt new file mode 100644 index 000000000..492936029 --- /dev/null +++ b/test/snapshots/parser/multiple_control_flow_test/test_0044_case_in_pattern_on_newline_in_same_ERB_tag_469f7105ed227c9918b8e8e22644591c-2ffd01e26b8c99a6c7a6dad67c9489dc.txt @@ -0,0 +1,50 @@ +--- +source: "Parser::MultipleControlFlowTest#test_0044_case in pattern on newline in same ERB tag" +input: |2- +<% case value + in 1 %> + One +<% in 2 %> + Two +<% end %> +options: {strict: false} +--- +@ DocumentNode (location: (1:0)-(7:0)) +└── children: (2 items) + ├── @ ERBCaseMatchNode (location: (1:0)-(6:9)) + │ ├── tag_opening: "<%" (location: (1:0)-(1:2)) + │ ├── content: " case value + │ in 1 " (location: (1:2)-(2:8)) + │ ├── tag_closing: "%>" (location: (2:8)-(2:10)) + │ ├── children: [] + │ ├── conditions: (2 items) + │ │ ├── @ ERBInNode (location: (2:10)-(4:0)) + │ │ │ ├── tag_opening: ∅ + │ │ │ ├── content: ∅ + │ │ │ ├── tag_closing: ∅ + │ │ │ ├── then_keyword: ∅ + │ │ │ └── statements: (1 item) + │ │ │ └── @ HTMLTextNode (location: (2:10)-(4:0)) + │ │ │ └── content: "\n One\n" + │ │ │ + │ │ │ + │ │ └── @ ERBInNode (location: (4:0)-(4:10)) + │ │ ├── tag_opening: "<%" (location: (4:0)-(4:2)) + │ │ ├── content: " in 2 " (location: (4:2)-(4:8)) + │ │ ├── tag_closing: "%>" (location: (4:8)-(4:10)) + │ │ ├── then_keyword: ∅ + │ │ └── statements: (1 item) + │ │ └── @ HTMLTextNode (location: (4:10)-(6:0)) + │ │ └── content: "\n Two\n" + │ │ + │ │ + │ ├── else_clause: ∅ + │ └── end_node: + │ └── @ ERBEndNode (location: (6:0)-(6:9)) + │ ├── tag_opening: "<%" (location: (6:0)-(6:2)) + │ ├── content: " end " (location: (6:2)-(6:7)) + │ └── tag_closing: "%>" (location: (6:7)-(6:9)) + │ + │ + └── @ HTMLTextNode (location: (6:9)-(7:0)) + └── content: "\n" \ No newline at end of file