Skip to content

Commit 6de7a10

Browse files
authored
Revert "Add support for TypeScript import assignments (#149)" (#158)
This reverts commit c07aeca.
1 parent 289f75b commit 6de7a10

File tree

7 files changed

+28
-390
lines changed

7 files changed

+28
-390
lines changed

README.md

+1-16
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,6 @@ import g from ".";
269269
import h from "./constants";
270270
import i from "./styles";
271271

272-
// TypeScript import assignments.
273-
import J = require("../parent");
274-
import K = require("./sibling");
275-
export import L = require("an-npm-package");
276-
import M = require("different-npm-package");
277-
import N = Namespace;
278-
export import O = Namespace.A.B.C;
279-
import P = Namespace.A.C;
280-
281272
// Different types of exports:
282273
export { a } from "../..";
283274
export { b } from "/";
@@ -389,8 +380,6 @@ Side effect imports have `\u0000` _prepended_ to their `from` string (starts wit
389380

390381
Type imports have `\u0000` _appended_ to their `from` string (ends with `\u0000`). You can match them with `"\\u0000$"` – but you probably need more than that to avoid them also being matched by other regexes.
391382

392-
TypeScript import assignments have `\u0001` (for `import A = require("A")`) or `\u0002` (for `import A = B.C.D`) prepended to their `from` string (starts with `\u0001` or `\u0002`). It is _not_ possible to distinguish `export import A =` and `import A =`.
393-
394383
All imports that match the same regex are sorted internally as mentioned in [Sort order].
395384

396385
This is the default value for the `groups` option:
@@ -410,8 +399,6 @@ This is the default value for the `groups` option:
410399
// Relative imports.
411400
// Anything that starts with a dot.
412401
["^\\."],
413-
// TypeScript import assignments.
414-
["^\\u0001", "^\\u0002"],
415402
];
416403
```
417404

@@ -530,8 +517,6 @@ The final whitespace rule is that this plugin puts one import/export per line. I
530517

531518
No. This is intentional to keep things simple. Use some other sorting rule, such as [import/order], for sorting `require`. Or consider migrating your code using `require` to `import`. `import` is well supported these days.
532519

533-
The only `require`-like thing supported is TypeScript import assignments like `import Thing = require("something")`. They’re much easier to support since they are very restricted: The thing to the left of the `=` has to be a single identifier, and inside `require()` there has to be a single string literal. This makes it sortable as if it was `import Thing from "something"`.
534-
535520
### Why sort on `from`?
536521

537522
Some other import sorting rules sort based on the first name after `import`, rather than the string after `from`. This plugin intentionally sorts on the `from` string to be `git diff` friendly.
@@ -707,7 +692,7 @@ Use [custom grouping], setting the `groups` option to only have a single inner a
707692
For example, here’s the default value but changed to a single inner array:
708693

709694
```js
710-
[["^\\u0000", "^node:", "^@?\\w", "^", "^\\.", "^\\u0001", "^\\u0002"]];
695+
[["^\\u0000", "^node:", "^@?\\w", "^", "^\\."]];
711696
```
712697

713698
(By default, each string is in its _own_ array (that’s 5 inner arrays) – causing a blank line between each.)

examples/.eslintrc.js

+4-7
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ module.exports = {
103103
"error",
104104
{
105105
// The default grouping, but with no blank lines.
106-
groups: [["^\\u0000", "^node:", "^@?\\w", "^", "^\\.", "^\\u0001", "^\\u0002"]],
106+
groups: [["^\\u0000", "^node:", "^@?\\w", "^", "^\\."]],
107107
},
108108
],
109109
},
@@ -115,7 +115,7 @@ module.exports = {
115115
"error",
116116
{
117117
// The default grouping, but in reverse.
118-
groups: [["^\\u0001", "^\\u0002"], ["^\\."], ["^"], ["^@?\\w"], ["^node:"], ["^\\u0000"]],
118+
groups: [["^\\."], ["^"], ["^@?\\w"], ["^node:"], ["^\\u0000"]],
119119
},
120120
],
121121
},
@@ -128,7 +128,7 @@ module.exports = {
128128
"error",
129129
{
130130
// The default grouping, but with type imports first as a separate group.
131-
groups: [["^.*\\u0000$"], ["^\\u0000"], ["^node:"], ["^@?\\w"], ["^"], ["^\\."], ["^\\u0001", "^\\u0002"]],
131+
groups: [["^.*\\u0000$"], ["^\\u0000"], ["^node:"], ["^@?\\w"], ["^"], ["^\\."]],
132132
},
133133
],
134134
},
@@ -141,7 +141,7 @@ module.exports = {
141141
"error",
142142
{
143143
// The default grouping, but with type imports last as a separate group.
144-
groups: [["^\\u0000"], ["^node:"], ["^@?\\w"], ["^"], ["^\\."], ["^\\u0001", "^\\u0002"], ["^.+\\u0000$"]],
144+
groups: [["^\\u0000"], ["^node:"], ["^@?\\w"], ["^"], ["^\\."], ["^.+\\u0000$"]],
145145
},
146146
],
147147
},
@@ -162,7 +162,6 @@ module.exports = {
162162
["^@?\\w"],
163163
["^"],
164164
["^\\."],
165-
["^\\u0001", "^\\u0002"],
166165
],
167166
},
168167
],
@@ -183,7 +182,6 @@ module.exports = {
183182
["^@?\\w"],
184183
["^"],
185184
["^\\."],
186-
["^\\u0001", "^\\u0002"],
187185
["^node:.*\\u0000$", "^@?\\w.*\\u0000$", "^[^.].*\\u0000$", "^\\..*\\u0000$"],
188186
],
189187
},
@@ -204,7 +202,6 @@ module.exports = {
204202
["^@?\\w.*\\u0000$", "^@?\\w"],
205203
["(?<=\\u0000)$", "^"],
206204
["^\\..*\\u0000$", "^\\."],
207-
["^\\u0001", "^\\u0002"],
208205
],
209206
},
210207
],

examples/readme-order.prettier.ts

-9
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,6 @@ import g from ".";
2525
import h from "./constants";
2626
import i from "./styles";
2727

28-
// TypeScript import assignments.
29-
import J = require("../parent");
30-
import K = require("./sibling");
31-
export import L = require("an-npm-package");
32-
import M = require("different-npm-package");
33-
import N = Namespace;
34-
export import O = Namespace.A.B.C;
35-
import P = Namespace.A.C;
36-
3728
// Different types of exports:
3829
export { a } from "../..";
3930
export { b } from "/";

src/imports.js

+14-57
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ const defaultGroups = [
1616
// Relative imports.
1717
// Anything that starts with a dot.
1818
["^\\."],
19-
// TypeScript import assignments.
20-
["^\\u0001", "^\\u0002"],
2119
];
2220

2321
module.exports = {
@@ -58,7 +56,7 @@ module.exports = {
5856
const parents = new Set();
5957

6058
return {
61-
"ImportDeclaration,TSImportEqualsDeclaration": (node) => {
59+
ImportDeclaration: (node) => {
6260
parents.add(node.parent);
6361
},
6462

@@ -99,16 +97,14 @@ function makeSortedItems(items, outerGroups) {
9997

10098
for (const item of items) {
10199
const { originalSource } = item.source;
102-
const sourceWithControlCharacter = getSourceWithControlCharacter(
103-
originalSource,
104-
item
105-
);
100+
const source = item.isSideEffectImport
101+
? `\0${originalSource}`
102+
: item.source.kind !== "value"
103+
? `${originalSource}\0`
104+
: originalSource;
106105
const [matchedGroup] = shared
107106
.flatMap(itemGroups, (groups) =>
108-
groups.map((group) => [
109-
group,
110-
group.regex.exec(sourceWithControlCharacter),
111-
])
107+
groups.map((group) => [group, group.regex.exec(source)])
112108
)
113109
.reduce(
114110
([group, longestMatch], [nextGroup, nextMatch]) =>
@@ -134,41 +130,14 @@ function makeSortedItems(items, outerGroups) {
134130
);
135131
}
136132

137-
function getSourceWithControlCharacter(originalSource, item) {
138-
if (item.isSideEffectImport) {
139-
return `\0${originalSource}`;
140-
}
141-
switch (item.source.kind) {
142-
case shared.KIND_VALUE:
143-
return originalSource;
144-
case shared.KIND_TS_IMPORT_ASSIGNMENT_REQUIRE:
145-
return `\u0001${originalSource}`;
146-
case shared.KIND_TS_IMPORT_ASSIGNMENT_NAMESPACE:
147-
return `\u0002${originalSource}`;
148-
default: // `type` and `typeof`.
149-
return `${originalSource}\u0000`;
150-
}
151-
}
152-
153133
// Exclude "ImportDefaultSpecifier" – the "def" in `import def, {a, b}`.
154134
function getSpecifiers(importNode) {
155-
switch (importNode.type) {
156-
case "ImportDeclaration":
157-
return importNode.specifiers.filter((node) => isImportSpecifier(node));
158-
case "TSImportEqualsDeclaration":
159-
return [];
160-
// istanbul ignore next
161-
default:
162-
throw new Error(`Unsupported import node type: ${importNode.type}`);
163-
}
135+
return importNode.specifiers.filter((node) => isImportSpecifier(node));
164136
}
165137

166138
// Full import statement.
167139
function isImport(node) {
168-
return (
169-
node.type === "ImportDeclaration" ||
170-
node.type === "TSImportEqualsDeclaration"
171-
);
140+
return node.type === "ImportDeclaration";
172141
}
173142

174143
// import def, { a, b as c, type d } from "A"
@@ -181,21 +150,9 @@ function isImportSpecifier(node) {
181150
// But not: import {} from "setup"
182151
// And not: import type {} from "setup"
183152
function isSideEffectImport(importNode, sourceCode) {
184-
switch (importNode.type) {
185-
case "ImportDeclaration":
186-
return (
187-
importNode.specifiers.length === 0 &&
188-
(!importNode.importKind ||
189-
importNode.importKind === shared.KIND_VALUE) &&
190-
!shared.isPunctuator(
191-
sourceCode.getFirstToken(importNode, { skip: 1 }),
192-
"{"
193-
)
194-
);
195-
case "TSImportEqualsDeclaration":
196-
return false;
197-
// istanbul ignore next
198-
default:
199-
throw new Error(`Unsupported import node type: ${importNode.type}`);
200-
}
153+
return (
154+
importNode.specifiers.length === 0 &&
155+
(!importNode.importKind || importNode.importKind === "value") &&
156+
!shared.isPunctuator(sourceCode.getFirstToken(importNode, { skip: 1 }), "{")
157+
);
201158
}

src/shared.js

+9-81
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ function getImportExportItems(
164164
const [start] = all[0].range;
165165
const [, end] = all[all.length - 1].range;
166166

167-
const source = getSource(sourceCode, node);
167+
const source = getSource(node);
168168

169169
return {
170170
node,
@@ -795,8 +795,8 @@ function isNewline(node) {
795795
return node.type === "Newline";
796796
}
797797

798-
function getSource(sourceCode, node) {
799-
const [source, kind] = getSourceTextAndKind(sourceCode, node);
798+
function getSource(node) {
799+
const source = node.source.value;
800800

801801
return {
802802
// Sort by directory level rather than by string length.
@@ -806,7 +806,7 @@ function getSource(sourceCode, node) {
806806
// Make `../` sort after `../../` but before `../a` etc.
807807
// Why a comma? See the next comment.
808808
.replace(/^[./]*\/$/, "$&,")
809-
// Make `.` and `/` sort before any other punctuation.
809+
// Make `.` and `/` sort before any other punctation.
810810
// The default order is: _ - , x x x . x x x / x x x
811811
// We’re changing it to: . / , x x x _ x x x - x x x
812812
.replace(/[./_-]/g, (char) => {
@@ -825,85 +825,16 @@ function getSource(sourceCode, node) {
825825
}
826826
}),
827827
originalSource: source,
828-
kind,
828+
kind: getImportExportKind(node),
829829
};
830830
}
831831

832-
function getSourceTextAndKind(sourceCode, node) {
833-
switch (node.type) {
834-
case "ImportDeclaration":
835-
case "ExportNamedDeclaration":
836-
case "ExportAllDeclaration":
837-
return [node.source.value, getImportExportKind(node)];
838-
case "TSImportEqualsDeclaration":
839-
return getSourceTextAndKindFromModuleReference(
840-
sourceCode,
841-
node.moduleReference
842-
);
843-
// istanbul ignore next
844-
default:
845-
throw new Error(`Unsupported import/export node type: ${node.type}`);
846-
}
847-
}
848-
849-
const KIND_VALUE = "value";
850-
const KIND_TS_IMPORT_ASSIGNMENT_REQUIRE = "z_require";
851-
const KIND_TS_IMPORT_ASSIGNMENT_NAMESPACE = "z_namespace";
852-
853-
function getSourceTextAndKindFromModuleReference(sourceCode, node) {
854-
switch (node.type) {
855-
case "TSExternalModuleReference":
856-
// Only string literals inside `require()` are allowed by
857-
// TypeScript, but the parser supports anything. Sorting
858-
// is defined for string literals only. For other expressions,
859-
// we just make sure not to crash.
860-
switch (node.expression.type) {
861-
case "Literal":
862-
return [
863-
typeof node.expression.value === "string"
864-
? node.expression.value
865-
: node.expression.raw,
866-
KIND_TS_IMPORT_ASSIGNMENT_REQUIRE,
867-
];
868-
default: {
869-
const [start, end] = node.expression.range;
870-
return [
871-
sourceCode.text.slice(start, end),
872-
KIND_TS_IMPORT_ASSIGNMENT_REQUIRE,
873-
];
874-
}
875-
}
876-
case "TSQualifiedName":
877-
return [
878-
getSourceTextFromTSQualifiedName(sourceCode, node),
879-
KIND_TS_IMPORT_ASSIGNMENT_NAMESPACE,
880-
];
881-
case "Identifier":
882-
return [node.name, KIND_TS_IMPORT_ASSIGNMENT_NAMESPACE];
883-
// istanbul ignore next
884-
default:
885-
throw new Error(`Unsupported module reference node type: ${node.type}`);
886-
}
887-
}
888-
889-
function getSourceTextFromTSQualifiedName(sourceCode, node) {
890-
switch (node.left.type) {
891-
case "Identifier":
892-
return `${node.left.name}.${node.right.name}`;
893-
case "TSQualifiedName":
894-
return `${getSourceTextFromTSQualifiedName(sourceCode, node.left)}.${
895-
node.right.name
896-
}`;
897-
// istanbul ignore next
898-
default:
899-
throw new Error(`Unsupported TS qualified name node type: ${node.type}`);
900-
}
901-
}
902-
903832
function getImportExportKind(node) {
904833
// `type` and `typeof` imports, as well as `type` exports (there are no
905-
// `typeof` exports).
906-
return node.importKind || node.exportKind || KIND_VALUE;
834+
// `typeof` exports). In Flow, import specifiers can also have a kind. Default
835+
// to "value" (like TypeScript) to make regular imports/exports come after the
836+
// type imports/exports.
837+
return node.importKind || node.exportKind || "value";
907838
}
908839

909840
// Like `Array.prototype.findIndex`, but searches from the end.
@@ -936,9 +867,6 @@ module.exports = {
936867
getImportExportItems,
937868
getSourceCode,
938869
isPunctuator,
939-
KIND_TS_IMPORT_ASSIGNMENT_NAMESPACE,
940-
KIND_TS_IMPORT_ASSIGNMENT_REQUIRE,
941-
KIND_VALUE,
942870
maybeReportSorting,
943871
printSortedItems,
944872
printWithSortedSpecifiers,

test/__snapshots__/examples.test.js.snap

-9
Original file line numberDiff line numberDiff line change
@@ -496,15 +496,6 @@ import g from ".";
496496
import h from "./constants";
497497
import i from "./styles";
498498
499-
// TypeScript import assignments.
500-
import J = require("../parent");
501-
import K = require("./sibling");
502-
export import L = require("an-npm-package");
503-
import M = require("different-npm-package");
504-
import N = Namespace;
505-
export import O = Namespace.A.B.C;
506-
import P = Namespace.A.C;
507-
508499
// Different types of exports:
509500
export { a } from "../..";
510501
export { b } from "/";

0 commit comments

Comments
 (0)