Skip to content

Commit f57b913

Browse files
authored
Support imports and exports anywhere (#123)
1 parent 3968369 commit f57b913

File tree

6 files changed

+124
-22
lines changed

6 files changed

+124
-22
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2018, 2019, 2020, 2022 Simon Lydell
3+
Copyright (c) 2018, 2019, 2020, 2022, 2023 Simon Lydell
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

src/exports.js

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,39 @@ module.exports = {
1414
sort: "Run autofix to sort these exports!",
1515
},
1616
},
17-
create: (context) => ({
18-
Program: (programNode) => {
19-
const sourceCode = context.getSourceCode();
20-
for (const chunk of shared.extractChunks(programNode, (node, lastNode) =>
21-
isPartOfChunk(node, lastNode, sourceCode)
22-
)) {
23-
maybeReportChunkSorting(chunk, context);
24-
}
25-
},
26-
ExportNamedDeclaration: (node) => {
27-
if (node.source == null && node.declaration == null) {
28-
maybeReportExportSpecifierSorting(node, context);
17+
create: (context) => {
18+
const parents = new Set();
19+
20+
const addParent = (node) => {
21+
if (isExportFrom(node)) {
22+
parents.add(node.parent);
2923
}
30-
},
31-
}),
24+
};
25+
26+
return {
27+
ExportNamedDeclaration: (node) => {
28+
if (node.source == null && node.declaration == null) {
29+
maybeReportExportSpecifierSorting(node, context);
30+
} else {
31+
addParent(node);
32+
}
33+
},
34+
35+
ExportAllDeclaration: addParent,
36+
37+
"Program:exit": () => {
38+
const sourceCode = context.getSourceCode();
39+
for (const parent of parents) {
40+
for (const chunk of shared.extractChunks(parent, (node, lastNode) =>
41+
isPartOfChunk(node, lastNode, sourceCode)
42+
)) {
43+
maybeReportChunkSorting(chunk, context);
44+
}
45+
}
46+
parents.clear();
47+
},
48+
};
49+
},
3250
};
3351

3452
function maybeReportChunkSorting(chunk, context) {

src/imports.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,27 @@ module.exports = {
4848
},
4949
create: (context) => {
5050
const { groups: rawGroups = defaultGroups } = context.options[0] || {};
51+
5152
const outerGroups = rawGroups.map((groups) =>
5253
groups.map((item) => RegExp(item, "u"))
5354
);
55+
56+
const parents = new Set();
57+
5458
return {
55-
Program: (programNode) => {
56-
for (const chunk of shared.extractChunks(programNode, (node) =>
57-
isImport(node) ? "PartOfChunk" : "NotPartOfChunk"
58-
)) {
59-
maybeReportChunkSorting(chunk, context, outerGroups);
59+
ImportDeclaration: (node) => {
60+
parents.add(node.parent);
61+
},
62+
63+
"Program:exit": () => {
64+
for (const parent of parents) {
65+
for (const chunk of shared.extractChunks(parent, (node) =>
66+
isImport(node) ? "PartOfChunk" : "NotPartOfChunk"
67+
)) {
68+
maybeReportChunkSorting(chunk, context, outerGroups);
69+
}
6070
}
71+
parents.clear();
6172
},
6273
};
6374
},

src/shared.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
// A “chunk” is a sequence of statements of a certain type with only comments
44
// and whitespace between.
5-
function extractChunks(programNode, isPartOfChunk) {
5+
function extractChunks(parentNode, isPartOfChunk) {
66
const chunks = [];
77
let chunk = [];
88
let lastNode = undefined;
99

10-
for (const node of programNode.body) {
10+
for (const node of parentNode.body) {
1111
const result = isPartOfChunk(node, lastNode);
1212
switch (result) {
1313
case "PartOfChunk":

test/exports.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,42 @@ const typescriptTests = {
11061106
},
11071107
errors: 1,
11081108
},
1109+
1110+
// Exports inside module declarations.
1111+
{
1112+
code: input`
1113+
|export type {X} from "X";
1114+
|export type {B} from "./B";
1115+
|
1116+
|declare module 'my-module' {
1117+
| export type { PlatformPath, ParsedPath } from 'path';
1118+
| export { type CopyOptions } from 'fs'; interface Something {}
1119+
| export {a, type type as type, z} from "../type";
1120+
| // comment
1121+
| export * as d from "d"
1122+
|export {c} from "c"; /*
1123+
| */\texport {} from "b"; // b
1124+
|}
1125+
`,
1126+
output: (actual) => {
1127+
expect(actual).toMatchInlineSnapshot(`
1128+
|export type {B} from "./B";
1129+
|export type {X} from "X";
1130+
|
1131+
|declare module 'my-module' {
1132+
| export { type CopyOptions } from 'fs';
1133+
| export type { ParsedPath,PlatformPath } from 'path';interface Something {}
1134+
| export {type type as type, a, z} from "../type";
1135+
| // comment
1136+
|/*
1137+
| */→export {} from "b"; // b
1138+
|export {c} from "c";
1139+
| export * as d from "d"
1140+
|}
1141+
`);
1142+
},
1143+
errors: 4,
1144+
},
11091145
],
11101146
};
11111147

test/imports.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,43 @@ const typescriptTests = {
20002000
},
20012001
errors: 1,
20022002
},
2003+
2004+
// Imports inside module declarations.
2005+
{
2006+
code: input`
2007+
|import type { ParsedPath } from 'path';
2008+
|import type { CopyOptions } from 'fs';
2009+
|
2010+
|declare module 'my-module' {
2011+
| import type { PlatformPath, ParsedPath } from 'path';
2012+
| import { type CopyOptions } from 'fs';
2013+
| export function normalize(p: string): string;
2014+
| // comment
2015+
| import "d"
2016+
|import c from "c"; /*
2017+
| */\timport * as b from "b"; // b
2018+
|}
2019+
`,
2020+
output: (actual) => {
2021+
expect(actual).toMatchInlineSnapshot(`
2022+
|import type { CopyOptions } from 'fs';
2023+
|import type { ParsedPath } from 'path';
2024+
|
2025+
|declare module 'my-module' {
2026+
| import { type CopyOptions } from 'fs';
2027+
| import type { ParsedPath,PlatformPath } from 'path';
2028+
| export function normalize(p: string): string;
2029+
| // comment
2030+
| import "d"
2031+
|
2032+
|/*
2033+
| */→import * as b from "b"; // b
2034+
|import c from "c";
2035+
|}
2036+
`);
2037+
},
2038+
errors: 3,
2039+
},
20032040
],
20042041
};
20052042

0 commit comments

Comments
 (0)