Skip to content

Conversation

@tvararu
Copy link

@tvararu tvararu commented Jan 31, 2026

This adds test cases and a custom error to handle code like:

<% case variable when "a" %>
  A
<% when "b" %>
  B
<% else %>
  C
<% end %>

<% case value in 1 %>
  One
<% in 2 %>
  Two
<% end %>

While this is valid ERB, it poses issues for the parser, as it would mean we'd need to turn a single statement into multiple nodes.

Those same blocks can be rewritten as:

<% case variable %>
<% when "a" %>
  A
<% when "b" %>
  B
<% else %>
  C
<% end %>

<% case value %>
<% in 1 %>
  One
<% in 2 %>
  Two
<% end %>

Which is unambiguous to parse, and arguably more legible.

This adds a new ERBCaseWithConditionsInTagError to detect this pattern and direct users to split into separate tags.

This adds test cases and a custom error to handle code like:

```erb
<% case variable when "a" %>
  A
<% when "b" %>
  B
<% else %>
  C
<% end %>

<% case value in 1 %>
  One
<% in 2 %>
  Two
<% end %>
```

While this is valid ERB, it poses issues for the parser, as it would
mean we'd need to turn a single statement into multiple nodes.

Those same blocks can be rewritten as:

```erb
<% case variable %>
<% when "a" %>
  A
<% when "b" %>
  B
<% else %>
  C
<% end %>

<% case value %>
<% in 1 %>
  One
<% in 2 %>
  Two
<% end %>
```

Which is unambiguous to parse, and arguably more legible.

This adds a new ERBCaseWithConditionsInTagError to detect this pattern
and direct users to split into separate tags.
Also use `inline_conditionals_count` instead of
`has_case_with_inline_conditions`.
@tvararu
Copy link
Author

tvararu commented Feb 3, 2026

@marcoroth I tried approaching this in a different way, like:

if ((analyzed->case_node_count > 0 && analyzed->when_node_count > 0) ||
    (analyzed->case_match_node_count > 0 && analyzed->in_node_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
  );
}

But it doesn't look like case x when "a" increments the when_node_count, it stays 0...

We have to add something to src/analyzed_ruby.c as the analyzed struct doesn't store enough information for us to infer whether a case node has inline conditionals; case_node->conditions.size is what we need but we need to extract it somewhere...

We could have analyzed->inline_conditionals_count, that would be an int instead of a boolean so it's more consistent with the rest of the struct. I pushed up a new commit with this but it's very similar to the boolean one, I've also changed the error name and the message

If you like this approach better I can rebase and squash the commits 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant