Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfd1ae63

Browse files
Xunnamiusljharb
authored andcommitted
[New]order: addsortTypesGroup option to allow intragroup sorting of type-only imports
Closes#2912Closes#2347Closes#2441Subsumes#2615
1 parent341178d commitfd1ae63

File tree

4 files changed

+274
-7
lines changed

4 files changed

+274
-7
lines changed

‎CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
1010
- add[`enforce-node-protocol-usage`] rule and`import/node-version` setting ([#3024], thanks[@GoldStrikeArch] and[@sevenc-nanashi])
1111
- add TypeScript types ([#3097], thanks[@G-Rath])
1212
-[`extensions`]: add `pathGroupOverrides to allow enforcement decision overrides based on specifier ([#3105], thanks[@Xunnamius])
13+
-[`order`]: add`sortTypesGroup` option to allow intragroup sorting of type-only imports ([#3104], thanks[@Xunnamius])
1314

1415
###Fixed
1516
-[`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks[@michaelfaith])
@@ -1174,6 +1175,7 @@ for info on changes for earlier releases.
11741175
[#3116]:https://github.com/import-js/eslint-plugin-import/pull/3116
11751176
[#3106]:https://github.com/import-js/eslint-plugin-import/pull/3106
11761177
[#3105]:https://github.com/import-js/eslint-plugin-import/pull/3105
1178+
[#3104]:https://github.com/import-js/eslint-plugin-import/pull/3104
11771179
[#3097]:https://github.com/import-js/eslint-plugin-import/pull/3097
11781180
[#3073]:https://github.com/import-js/eslint-plugin-import/pull/3073
11791181
[#3072]:https://github.com/import-js/eslint-plugin-import/pull/3072

‎docs/rules/order.md

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ This rule supports the following options (none of which are required):
106106
-[`alphabetize`][30]
107107
-[`named`][33]
108108
-[`warnOnUnassignedImports`][5]
109+
-[`sortTypesGroup`][7]
109110

110111
---
111112

@@ -156,7 +157,7 @@ Roughly speaking, the grouping algorithm is as follows:
156157

157158
1. If the import has no corresponding identifiers (e.g.`import './my/thing.js'`), is otherwise "unassigned," or is an unsupported use of`require()`, and[`warnOnUnassignedImports`][5] is disabled, it will be ignored entirely since the order of these imports may be important for their[side-effects][31]
158159
2. If the import is part of an arcane TypeScript declaration (e.g.`import log = console.log`), it will be considered**object**. However, note that external module references (e.g.`import x = require('z')`) are treated as normal`require()`s and import-exports (e.g.`export import w = y;`) are ignored entirely
159-
3. If the import is[type-only][6],and`"type"` is in`groups`, it will be considered**type** (with additional implications if using[`pathGroups`][8] and`"type"` is in[`pathGroupsExcludedImportTypes`][9])
160+
3. If the import is[type-only][6],`"type"` is in`groups`, and[`sortTypesGroup`][7] is disabled, it will be considered**type** (with additional implications if using[`pathGroups`][8] and`"type"` is in[`pathGroupsExcludedImportTypes`][9])
160161
4. If the import's specifier matches[`import/internal-regex`][28], it will be considered**internal**
161162
5. If the import's specifier is an absolute path, it will be considered**unknown**
162163
6. If the import's specifier has the name of a Node.js core module (using[is-core-module][10]), it will be considered**builtin**
@@ -171,7 +172,7 @@ Roughly speaking, the grouping algorithm is as follows:
171172
15. If the import's specifier has a name that starts with a word character, it will be considered**external**
172173
16. If this point is reached, the import will be ignored entirely
173174

174-
At the end of the process, if they co-exist in the same file, all top-level`require()` statements that haven't been ignored are shifted (with respect to their order) below any ES6`import` or similar declarations.
175+
At the end of the process, if they co-exist in the same file, all top-level`require()` statements that haven't been ignored are shifted (with respect to their order) below any ES6`import` or similar declarations. Finally, any type-only declarations are potentially reorganized according to[`sortTypesGroup`][7].
175176

176177
###`pathGroups`
177178

@@ -533,6 +534,64 @@ import path from 'path';
533534
import'./styles.css';
534535
```
535536

537+
###`sortTypesGroup`
538+
539+
Valid values:`boolean`\
540+
Default:`false`
541+
542+
>\[!NOTE]
543+
>
544+
>This setting is only meaningful when`"type"` is included in[`groups`][18].
545+
546+
Sort[type-only imports][6] separately from normal non-type imports.
547+
548+
When enabled, the intragroup sort order of[type-only imports][6] will mirror the intergroup ordering of normal imports as defined by[`groups`][18],[`pathGroups`][8], etc.
549+
550+
####Example
551+
552+
Given the following settings:
553+
554+
```jsonc
555+
{
556+
"import/order": ["error", {
557+
"groups": ["type","builtin","parent","sibling","index"],
558+
"alphabetize": {"order":"asc" }
559+
}]
560+
}
561+
```
562+
563+
This will fail the rule check even though it's logically ordered as we expect (builtins come before parents, parents come before siblings, siblings come before indices), the only difference is we separated type-only imports from normal imports:
564+
565+
```ts
566+
importtypeAfrom"fs";
567+
importtypeBfrom"path";
568+
importtypeCfrom"../foo.js";
569+
importtypeDfrom"./bar.js";
570+
importtypeEfrom'./';
571+
572+
importafrom"fs";
573+
importbfrom"path";
574+
importcfrom"../foo.js";
575+
importdfrom"./bar.js";
576+
importefrom"./";
577+
```
578+
579+
This happens because[type-only imports][6] are considered part of one global
580+
[`"type"` group](#how-imports-are-grouped) by default. However, if we set
581+
`sortTypesGroup` to`true`:
582+
583+
```jsonc
584+
{
585+
"import/order": ["error", {
586+
"groups": ["type","builtin","parent","sibling","index"],
587+
"alphabetize": {"order":"asc" },
588+
"sortTypesGroup":true
589+
}]
590+
}
591+
```
592+
593+
The same example will pass.
594+
536595
##Related
537596

538597
-[`import/external-module-folders`][29]
@@ -543,6 +602,7 @@ import './styles.css';
543602
[4]:https://nodejs.org/api/esm.html#terminology
544603
[5]:#warnonunassignedimports
545604
[6]:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export
605+
[7]:#sorttypesgroup
546606
[8]:#pathgroups
547607
[9]:#pathgroupsexcludedimporttypes
548608
[10]:https://www.npmjs.com/package/is-core-module

‎src/rules/order.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -513,31 +513,43 @@ function computePathRank(ranks, pathGroups, path, maxPosition) {
513513
}
514514
}
515515

516-
functioncomputeRank(context,ranks,importEntry,excludedImportTypes){
516+
functioncomputeRank(context,ranks,importEntry,excludedImportTypes,isSortingTypesGroup){
517517
letimpType;
518518
letrank;
519+
520+
constisTypeGroupInGroups=ranks.omittedTypes.indexOf('type')===-1;
521+
constisTypeOnlyImport=importEntry.node.importKind==='type';
522+
constisExcludedFromPathRank=isTypeOnlyImport&&isTypeGroupInGroups&&excludedImportTypes.has('type');
523+
519524
if(importEntry.type==='import:object'){
520525
impType='object';
521-
}elseif(importEntry.node.importKind==='type'&&ranks.omittedTypes.indexOf('type')===-1){
526+
}elseif(isTypeOnlyImport&&isTypeGroupInGroups&&!isSortingTypesGroup){
522527
impType='type';
523528
}else{
524529
impType=importType(importEntry.value,context);
525530
}
526-
if(!excludedImportTypes.has(impType)){
531+
532+
if(!excludedImportTypes.has(impType)&&!isExcludedFromPathRank){
527533
rank=computePathRank(ranks.groups,ranks.pathGroups,importEntry.value,ranks.maxPosition);
528534
}
535+
529536
if(typeofrank==='undefined'){
530537
rank=ranks.groups[impType];
531538
}
539+
540+
if(isTypeOnlyImport&&isSortingTypesGroup){
541+
rank=ranks.groups.type+rank/10;
542+
}
543+
532544
if(importEntry.type!=='import'&&!importEntry.type.startsWith('import:')){
533545
rank+=100;
534546
}
535547

536548
returnrank;
537549
}
538550

539-
functionregisterNode(context,importEntry,ranks,imported,excludedImportTypes){
540-
constrank=computeRank(context,ranks,importEntry,excludedImportTypes);
551+
functionregisterNode(context,importEntry,ranks,imported,excludedImportTypes,isSortingTypesGroup){
552+
constrank=computeRank(context,ranks,importEntry,excludedImportTypes,isSortingTypesGroup);
541553
if(rank!==-1){
542554
imported.push({ ...importEntry, rank});
543555
}
@@ -781,6 +793,10 @@ module.exports = {
781793
'never',
782794
],
783795
},
796+
sortTypesGroup:{
797+
type:'boolean',
798+
default:false,
799+
},
784800
named:{
785801
default:false,
786802
oneOf:[{
@@ -837,6 +853,7 @@ module.exports = {
837853
constoptions=context.options[0]||{};
838854
constnewlinesBetweenImports=options['newlines-between']||'ignore';
839855
constpathGroupsExcludedImportTypes=newSet(options.pathGroupsExcludedImportTypes||['builtin','external','object']);
856+
constsortTypesGroup=options.sortTypesGroup;
840857

841858
constnamed={
842859
types:'mixed',
@@ -879,6 +896,9 @@ module.exports = {
879896
constimportMap=newMap();
880897
constexportMap=newMap();
881898

899+
constisTypeGroupInGroups=ranks.omittedTypes.indexOf('type')===-1;
900+
constisSortingTypesGroup=isTypeGroupInGroups&&sortTypesGroup;
901+
882902
functiongetBlockImports(node){
883903
if(!importMap.has(node)){
884904
importMap.set(node,[]);
@@ -932,6 +952,7 @@ module.exports = {
932952
ranks,
933953
getBlockImports(node.parent),
934954
pathGroupsExcludedImportTypes,
955+
isSortingTypesGroup,
935956
);
936957

937958
if(named.import){
@@ -983,6 +1004,7 @@ module.exports = {
9831004
ranks,
9841005
getBlockImports(node.parent),
9851006
pathGroupsExcludedImportTypes,
1007+
isSortingTypesGroup,
9861008
);
9871009
},
9881010
CallExpression(node){
@@ -1005,6 +1027,7 @@ module.exports = {
10051027
ranks,
10061028
getBlockImports(block),
10071029
pathGroupsExcludedImportTypes,
1030+
isSortingTypesGroup,
10081031
);
10091032
},
10101033
...named.require&&{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp