diff --git a/config.yml b/config.yml index 22376e286..34c161742 100644 --- a/config.yml +++ b/config.yml @@ -178,6 +178,13 @@ errors: fields: [] + - 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." + arguments: [] + + fields: [] + warnings: fields: [] types: [] diff --git a/src/analyze.c b/src/analyze.c index dcb49cd9a..48bdccf7f 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -72,6 +72,14 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) { erb_content_node->base.errors ); } + + if (analyzed->inline_conditionals_count > 0) { + append_erb_case_with_conditions_error( + erb_content_node->base.location.start, + erb_content_node->base.location.end, + erb_content_node->base.errors + ); + } } else { erb_content_node->parsed = false; erb_content_node->valid = true; diff --git a/src/analyze_helpers.c b/src/analyze_helpers.c index 27a5ca7f2..3d21bf7d4 100644 --- a/src/analyze_helpers.c +++ b/src/analyze_helpers.c @@ -406,6 +406,9 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) { if (has_location(case_node->case_keyword_loc) && !is_end_keyword(case_node->end_keyword_loc)) { analyzed->unclosed_control_flow_count++; + if (case_node->conditions.size > 0) { + analyzed->inline_conditionals_count++; + } } break; @@ -416,6 +419,13 @@ bool search_unclosed_control_flows(const pm_node_t* node, void* data) { if (has_location(case_match_node->case_keyword_loc) && !is_end_keyword(case_match_node->end_keyword_loc)) { analyzed->unclosed_control_flow_count++; + if (case_match_node->conditions.size > 0) { + analyzed->inline_conditionals_count++; + } + + if (case_match_node->predicate && case_match_node->predicate->type == PM_MATCH_PREDICATE_NODE) { + analyzed->inline_conditionals_count++; + } } break; diff --git a/src/analyzed_ruby.c b/src/analyzed_ruby.c index 4d0a7ac84..9c8f3c2bb 100644 --- a/src/analyzed_ruby.c +++ b/src/analyzed_ruby.c @@ -22,6 +22,7 @@ analyzed_ruby_T* init_analyzed_ruby(hb_string_T source) { analyzed->case_match_node_count = 0; analyzed->when_node_count = 0; analyzed->in_node_count = 0; + analyzed->inline_conditionals_count = 0; analyzed->for_node_count = 0; analyzed->while_node_count = 0; analyzed->until_node_count = 0; diff --git a/src/include/analyzed_ruby.h b/src/include/analyzed_ruby.h index 9956871da..245291905 100644 --- a/src/include/analyzed_ruby.h +++ b/src/include/analyzed_ruby.h @@ -21,6 +21,7 @@ typedef struct ANALYZED_RUBY_STRUCT { int case_match_node_count; int when_node_count; int in_node_count; + int inline_conditionals_count; int for_node_count; int while_node_count; int until_node_count; diff --git a/test/parser/multiple_control_flow_test.rb b/test/parser/multiple_control_flow_test.rb index 1573278e0..c4914bbc8 100644 --- a/test/parser/multiple_control_flow_test.rb +++ b/test/parser/multiple_control_flow_test.rb @@ -361,5 +361,25 @@ class MultipleControlFlowTest < Minitest::Spec %> ERB end + + test "case and when in same ERB tag" do + assert_parsed_snapshot(<<~ERB) + <% case variable when "a" %> + A + <% when "b" %> + B + <% end %> + ERB + end + + test "case in pattern in same ERB tag" do + assert_parsed_snapshot(<<~ERB) + <% case value in 1 %> + One + <% in 2 %> + Two + <% end %> + ERB + end end end 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.txt new file mode 100644 index 000000000..58b9869c4 --- /dev/null +++ b/test/snapshots/parser/multiple_control_flow_test/test_0041_case_and_when_in_same_ERB_tag_82797abe9bddf29a367f8ebcc420eaba.txt @@ -0,0 +1,44 @@ +--- +source: "Parser::MultipleControlFlowTest#test_0041_case and when in same ERB tag" +input: |2- +<% case variable when "a" %> + A +<% when "b" %> + B +<% end %> +--- +@ 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) + │ │ └── @ 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_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.txt new file mode 100644 index 000000000..a8fbbd0a2 --- /dev/null +++ b/test/snapshots/parser/multiple_control_flow_test/test_0042_case_in_pattern_in_same_ERB_tag_5655a054015224a72ca2f5d378f9b966.txt @@ -0,0 +1,44 @@ +--- +source: "Parser::MultipleControlFlowTest#test_0042_case in pattern in same ERB tag" +input: |2- +<% case value in 1 %> + One +<% in 2 %> + Two +<% end %> +--- +@ 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) + │ │ └── @ 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