Skip to content

Fix class extraction for Rails' strict locals#19525

Merged
RobinMalfait merged 5 commits intomainfrom
fix/issue-19481
Jan 6, 2026
Merged

Fix class extraction for Rails' strict locals#19525
RobinMalfait merged 5 commits intomainfrom
fix/issue-19481

Conversation

@RobinMalfait
Copy link
Member

@RobinMalfait RobinMalfait commented Jan 5, 2026

Fixes: #19481

This PR improves the Ruby extractor to better handle strict locals. We recently introduced skipping comments in the Ruby extractor (PR #19243 for #19239) by ignoring comments that start with # until the end of the line.

Strict locals are implemented like this:

<%# locals: (css: "text-amber-600") %>

Notice the # after the <%, we considered this a comment and ignored it.

This PR changes that behavior slightly where we skip comments that are preceded by %. This means that <%# anything here _will_ be scanned %>. This should solve the strict locals case, and normal comments will still be skipped.

We can be more strict in the future if needed, but I think that this should be a good solution for both scenarios.

Test plan

  1. Added a test to ensure we extract candidates in strict locals
  2. Added a regression test for issue Tailwind v4 parsing warnings when scanning Rails gem source files on Heroku #19239 where we introduced skipping comments in the Ruby extractor
  3. Other existing tests are still passing

We can also verify the extracted candidates:
(it's subtle, but you can see that the class is being extracted now)

image

This allows for strict-locals support.
This allows us to verify what the expected extracted candidates are.
We already have `test_extract_contains`, which just ensures that the
provided list is extracted (while ignoring some potential noise).
We introduced skipping comments in the Ruby extractor for issue #19239
This adds a regression test to make sure that the behavior is unchanged
@RobinMalfait RobinMalfait changed the title Fix class extraction Rails strict locals Fix class extraction for Rails' strict locals Jan 5, 2026
@RobinMalfait RobinMalfait marked this pull request as ready for review January 5, 2026 19:03
@RobinMalfait RobinMalfait requested a review from a team as a code owner January 5, 2026 19:03
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

Walkthrough

This pull request addresses the extraction of CSS class names from Rails' strict locals syntax. It updates the changelog, refactors test helpers in the pre-processor module by adding a new test_extract_exact function and renaming parameters for clarity, and modifies the Ruby pre-processor to conditionally treat '#' as a comment delimiter only when not preceded by '%'. This guards against misclassifying ERB-style comments in strict locals blocks. New tests validate comment handling and proper extraction of CSS classes from strict locals constructs.

Pre-merge checks

✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix class extraction for Rails' strict locals' clearly and specifically summarizes the main change addressing the issue with strict locals not extracting classes.
Description check ✅ Passed The description is detailed and directly related to the changeset, explaining the problem with strict locals, the solution implemented, and the test plan.
Linked Issues check ✅ Passed The PR directly addresses issue #19481 by modifying the Ruby extractor to skip comments only when '#' is not preceded by '%', enabling extraction of class strings from strict locals syntax.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing class extraction for Rails' strict locals. The test helpers and changelog update are in scope as supporting changes.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
crates/oxide/src/extractor/pre_processors/pre_processor.rs (2)

28-51: Exact extraction helper is correct; consider robustness to ordering

The helper correctly reuses Extractor and gathers both candidates and CSS variables, and the comparison logic is sound. If extraction order is not semantically important, you might want to normalize (e.g., sort) both candidates and expected before comparing to avoid brittle tests tied to traversal order.


54-75: Containment helper rename and loop update look good

Renaming itemsexpected and iterating for item in &expected keeps semantics intact and improves readability; the containment check against candidates remains correct.

You could consider sharing the candidate-collection logic between test_extract_exact and test_extract_contains to avoid duplication, but this is purely a test ergonomics tweak.

crates/oxide/src/extractor/pre_processors/ruby.rs (1)

403-429: test_strict_locals accurately captures the Rails strict‑locals scenario

The test input mirrors the <%# locals: (css: "…") %> pattern plus additional locals and static classes, and test_extract_contains asserts that all relevant class names (text-amber-600, text-sky-500, text-green-500) are discoverable. This directly validates the new guard around # comment stripping and provides solid coverage for the original bug report.

If you later want stronger guarantees here, you could switch to test_extract_exact with a full expected list to ensure no unexpected candidates are introduced from the strict‑locals line.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c07d4a7 and 5ef8cee.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • crates/oxide/src/extractor/pre_processors/pre_processor.rs
  • crates/oxide/src/extractor/pre_processors/ruby.rs
🧰 Additional context used
🧬 Code graph analysis (2)
crates/oxide/src/extractor/pre_processors/ruby.rs (1)
crates/oxide/src/extractor/pre_processors/pre_processor.rs (3)
  • test (5-25)
  • test_extract_exact (28-51)
  • test_extract_contains (54-85)
crates/oxide/src/extractor/pre_processors/pre_processor.rs (3)
crates/oxide/src/extractor/mod.rs (1)
  • new (65-72)
crates/oxide/src/cursor.rs (1)
  • new (30-42)
crates/oxide/src/extractor/machine.rs (1)
  • new (13-15)
🔇 Additional comments (3)
CHANGELOG.md (1)

16-16: Changelog entry is consistent and clear

The new “Rails' strict locals” fix entry matches surrounding formatting and scope; no changes needed.

crates/oxide/src/extractor/pre_processors/ruby.rs (2)

122-126: Guarding comment stripping by previous byte matches strict‑locals requirement

Conditioning the # comment handling on cursor.prev not being % ensures <%# locals: … %> blocks are no longer treated as comments while ordinary Ruby # comments (including the RDoc cross‑reference examples and trailing comments after code) are still stripped. This aligns with the strict‑locals use case without impacting %w#…# handling or string literals.


390-401: test_skip_comments gives a precise regression check for comment handling

This test nicely locks in the expectation that pure comment blocks (including RDoc cross‑refs) yield no extracted candidates by using test_extract_exact with an empty vector. That’s a good targeted regression for the earlier “skip comments” behavior.

@RobinMalfait RobinMalfait merged commit 25f7ccf into main Jan 6, 2026
7 checks passed
@RobinMalfait RobinMalfait deleted the fix/issue-19481 branch January 6, 2026 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Class extraction with Rails' strict locals

1 participant

Comments