Skip to content

Commit

Permalink
Fix invalid output code when eliding TS star imports
Browse files Browse the repository at this point in the history
From some manual testing, I noticed that the code:
```ts
import A, * as B from "./A";
console.log(A);
```
becomes this invalid code:
```ts
import A, from "./A";
console.log(A);
```
The `* as B` was being elided because it's treated as a type-only import, but in
this case we need to elide the comma as well since there's no concept of
"trailing commas" here. The code to do that is a little clunky, but I ended up
always removing the comma and using a boolean to track whether it should be
added back.
  • Loading branch information
alangpierce committed Jul 14, 2022
1 parent 66da4d1 commit 98ee525
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
20 changes: 18 additions & 2 deletions src/transformers/ESMImportTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export default class ESMImportTransformer extends Transformer {
}

let foundNonTypeImport = false;
let needsComma = false;

if (this.tokens.matches1(tt.name)) {
if (this.isTypeName(this.tokens.identifierName())) {
Expand All @@ -172,23 +173,38 @@ export default class ESMImportTransformer extends Transformer {
foundNonTypeImport = true;
this.tokens.copyToken();
if (this.tokens.matches1(tt.comma)) {
this.tokens.copyToken();
// We're in a statement like:
// import A, * as B from './A';
// or
// import A, {foo} from './A';
// where the `A` is being kept. The comma should be removed if an only
// if the next part of the import statement is elided, but that's hard
// to determine at this point in the code. Instead, always remove it
// and set a flag to add it back if necessary.
needsComma = true;
this.tokens.removeToken();
}
}
}

if (this.tokens.matches1(tt.star)) {
if (this.isTypeName(this.tokens.identifierNameAtIndex(this.tokens.currentIndex() + 2))) {
if (this.isTypeName(this.tokens.identifierNameAtRelativeIndex(2))) {
this.tokens.removeToken();
this.tokens.removeToken();
this.tokens.removeToken();
} else {
if (needsComma) {
this.tokens.appendCode(",");
}
foundNonTypeImport = true;
this.tokens.copyExpectedToken(tt.star);
this.tokens.copyExpectedToken(tt.name);
this.tokens.copyExpectedToken(tt.name);
}
} else if (this.tokens.matches1(tt.braceL)) {
if (needsComma) {
this.tokens.appendCode(",");
}
this.tokens.copyToken();
while (!this.tokens.matches1(tt.braceR)) {
const specifierInfo = getImportExportSpecifierInfo(this.tokens);
Expand Down
23 changes: 23 additions & 0 deletions test/typescript-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,29 @@ describe("typescript transform", () => {
);
});

it("produces proper import statements when eliding ESM imported names", () => {
assertTypeScriptESMResult(
`
import keep1, * as elide1 from "./m1";
import keep2, * as keep3 from "./m2";
import elide2, * as keep4 from "./m3";
import keep5, {elide3} from "./m4";
import keep6, {keep7} from "./m5";
import elide4, {keep8} from "./m6";
console.log(keep1, keep2, keep3, keep4, keep5, keep6, keep7, keep8);
`,
`
import keep1 from "./m1";
import keep2, * as keep3 from "./m2";
import * as keep4 from "./m3";
import keep5, {} from "./m4";
import keep6, {keep7} from "./m5";
import {keep8} from "./m6";
console.log(keep1, keep2, keep3, keep4, keep5, keep6, keep7, keep8);
`,
);
});

it("handles import() types", () => {
assertTypeScriptESMResult(
`
Expand Down

0 comments on commit 98ee525

Please sign in to comment.