Skip to content

Conversation

@yslpn
Copy link
Contributor

@yslpn yslpn commented Dec 24, 2025

Remove empty statements using retain()

Removes empty statements (Stmt::Empty) from AST after Lingui macro transformations, following SWC ECMAScript Cheatsheet recommendations.

Problem

Empty statements remained in output after macro transformation:

// Before
import { t } from "@lingui/core/macro";
;
const msg = t`Hello`;
;
// After (without fix)
import { i18n as $_i18n } from "@lingui/core";
;
const msg = $_i18n._({ id: "...", message: "Hello" });
;
// After (with fix)
import { i18n as $_i18n } from "@lingui/core";
const msg = $_i18n._({ id: "...", message: "Hello" });

Solution

Uses retain() method instead of filter().collect() for better memory efficiency.

Implementation

In fold_stmts():

stmts.retain(|s| !matches!(s, Stmt::Empty(..)));

In fold_module_items():

n.retain(|item| !matches!(item, ModuleItem::Stmt(Stmt::Empty(..))));

See: SWC Fold trait

Tests

Added 7 tests in src/tests/empty_statements.rs covering:

  • Function blocks, arrow functions, nested blocks
  • Loops (for, while), try-catch, switch-case
  • Module level statements

Pros and Cons

Pros

  • Follows SWC best practices - Official cheatsheet recommends this approach
  • Cleaner output - No extra semicolons in transformed code
  • Better performance - retain() is more efficient than filter().collect()
  • No semantic changes - Empty statements don't affect code behavior
  • Formatter-friendly - Tools like Prettier/Biome would remove them anyway

Cons

  • Modifies user's code style - Removes semicolons that user explicitly wrote
  • Beyond plugin scope - Plugin's main job is Lingui macro transformation, not code cleanup

Decision

This change is OPTIONAL and not required for core functionality.

The plugin works correctly without removing empty statements. This PR improves output quality following SWC recommendations, but this PR could be close if original code style is preferred.

Results

-All 109 tests pass

  • Cleaner output without extra semicolons
  • Better performance with retain() vs filter().collect()

@codecov
Copy link

codecov bot commented Dec 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.21%. Comparing base (4d28b7f) to head (505895c).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #186      +/-   ##
==========================================
+ Coverage   92.17%   92.21%   +0.04%     
==========================================
  Files           8        8              
  Lines        1355     1375      +20     
==========================================
+ Hits         1249     1268      +19     
- Misses        106      107       +1     
Flag Coverage Δ
unittests 92.21% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/lib.rs 90.59% <100.00%> (+0.25%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@yslpn yslpn marked this pull request as draft December 29, 2025 09:24
@timofei-iatsenko
Copy link
Collaborator

I'm not sure i've followed the idea in this PR correctly, does the plugin itself introduce empty statements somehow during transformation?

From the PR description (and tests) it seems that empty statements were in the source code and kept in in the transpiled output - which is totally correct, as the plugin should not touch anything not related to it.

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.

2 participants