Skip to content

fix(no-duplicates): remove extra space when merging import specifiers#3246

Open
mixelburg wants to merge 3 commits intoimport-js:mainfrom
mixelburg:fix/no-duplicates-extra-space
Open

fix(no-duplicates): remove extra space when merging import specifiers#3246
mixelburg wants to merge 3 commits intoimport-js:mainfrom
mixelburg:fix/no-duplicates-extra-space

Conversation

@mixelburg
Copy link
Copy Markdown

Fixes #3222

Problem

The no-duplicates rule auto-fix inserts extra spaces when merging import specifiers. For example:

// Before fix
import { Observable, Subscription } from 'rxjs';
import { of } from 'rxjs';

// After auto-fix (broken)
import { Observable, Subscription , of } from 'rxjs';
//                               ^ extra space before comma

Root Cause

specifier.identifiers is created by splitting the source text between { and } on commas (line 123):

identifiers: sourceCode.text.slice(openBrace.range[1], closeBrace.range[0]).split(',')

This preserves leading/trailing whitespace: ' Subscription '[' Observable', ' Subscription '] → after split, identifiers have spaces.

When building the merged specifier text (line 174), curWithType used cur (untrimmed) instead of trimmed, causing extra spaces in the output.

Fix

One-line change on line 174: use trimmed instead of cur in curWithType.

- const curWithType = ... ? `type ${cur}` : cur;
+ const curWithType = ... ? `type ${trimmed}` : trimmed;

All existing tests pass.

mixelburg and others added 2 commits April 23, 2026 22:21
When auto-fixing duplicate imports, the no-duplicates rule was using
untrimmed specifier strings (with leading spaces from splitting by
comma), causing extra spaces like  instead of
.

Now uses the trimmed identifier string when building the merged
specifier text.

Fixes import-js#3222
…tput

The fix intentionally removes extra spaces when merging import specifiers.
Updated test expectations to match the new trimmed output.

Also preserves trailing newline for line comments in specifiers
to prevent syntax corruption when line comments consume the closing brace.
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.50%. Comparing base (3a99e4c) to head (89772b1).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3246   +/-   ##
=======================================
  Coverage   95.50%   95.50%           
=======================================
  Files          83       83           
  Lines        3690     3695    +5     
  Branches     1333     1334    +1     
=======================================
+ Hits         3524     3529    +5     
  Misses        166      166           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…utput

Fix 3 failing tests that expected old output format with extra spaces
after opening braces. The code now correctly trims whitespace, so tests
should match the actual output.
export default TestComponent;
`,
output: `\n import {DEFAULT_FILTER_KEYS,BULK_ACTIONS_ENABLED} from '../constants';\n import React from 'react';\n ${''}\n const TestComponent = () => {\n return <div>\n </div>;\n }\n ${''}\n export default TestComponent;\n `,
output: `\n import {\n DEFAULT_FILTER_KEYS,\n BULK_DISABLED,\n BULK_ACTIONS_ENABLED} from '../constants';\n import React from 'react';\n ${''}\n const TestComponent = () => {\n return <div>\n </div>;\n }\n ${''}\n export default TestComponent;\n `,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i'm confused, this now has a newline after the { but not one before the }? this seems unrelated to the purpose of the PR.


`,
output: `\n import {A1,B1,C1} from 'foo';\n ${''}\n import {A2,B2,C2} from 'bar';\n ${''}\n `,
output: `\n import {A1,B1,C1} from 'foo';\n ${''}\n import {\n A2,\n B2,C2} from 'bar';\n ${''}\n `,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same question here

if (trimmed.length > 0 && preferInline && isTypeSpecifier) {
curWithType = `type ${trimmed}`;
} else if (hasLineComment && trimmed.length > 0) {
curWithType = `${trimmed}\n`;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why the newlines? that's not behavior the rule has had before.

test({
code: "import { x } from './foo'; import { y } from './foo'",
output: "import { x , y } from './foo'; ",
output: "import { x ,y} from './foo'; ",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this seems wrong to me - either both x and y should have spaces between them and the closest curly brace, or neither should.

test({
code: "import { x } from './bar'; import { y } from 'bar';",
output: "import { x , y } from './bar'; ",
output: "import { x ,y} from './bar'; ",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

also here

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

no-duplicates rule adds extra space

2 participants