@borela-tech/eslint-config 2.1.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +273 -34
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/index.ts +18 -5
- package/src/rules/__tests__/importsAndReExportsAtTop.test.ts +3 -1
- package/src/rules/__tests__/individualImports.test.ts +3 -1
- package/src/rules/__tests__/individualReExports.test.ts +3 -1
- package/src/rules/__tests__/multilineUnionTypes.test.ts +75 -0
- package/src/rules/__tests__/singleLineImports.test.ts +129 -0
- package/src/rules/__tests__/singleLineReExports.test.ts +100 -0
- package/src/rules/__tests__/sortedImports.test.ts +37 -1
- package/src/rules/__tests__/sortedReExports.test.ts +27 -1
- package/src/rules/importsAndReExportsAtTop/CategorizedStatements.ts +2 -2
- package/src/rules/importsAndReExportsAtTop/categorizeStatements.ts +7 -6
- package/src/rules/importsAndReExportsAtTop/generateSortedText.ts +4 -6
- package/src/rules/importsAndReExportsAtTop/getStatementType.ts +1 -1
- package/src/rules/importsAndReExportsAtTop/index.ts +5 -5
- package/src/rules/importsAndReExportsAtTop/isImportDeclaration.ts +7 -0
- package/src/rules/importsAndReExportsAtTop/isReExport.ts +12 -0
- package/src/rules/individualImports.ts +4 -3
- package/src/rules/individualReExports.ts +8 -9
- package/src/rules/multilineUnionTypes/createFix.ts +13 -0
- package/src/rules/multilineUnionTypes/index.ts +52 -0
- package/src/rules/multilineUnionTypes/isMultiline.ts +6 -0
- package/src/rules/singleLineImports/createFix.ts +23 -0
- package/src/rules/singleLineImports/formatAttributes.ts +20 -0
- package/src/rules/singleLineImports/formatNamed.ts +9 -0
- package/src/rules/singleLineImports/formatSpecifiers.ts +32 -0
- package/src/rules/singleLineImports/index.ts +34 -0
- package/src/rules/singleLineImports/isMultiline.ts +6 -0
- package/src/rules/singleLineReExports/createFix.ts +29 -0
- package/src/rules/singleLineReExports/index.ts +48 -0
- package/src/rules/singleLineReExports/isMultiline.ts +6 -0
- package/src/rules/sortedImports/ImportError.ts +4 -1
- package/src/rules/sortedImports/ImportGroup.ts +2 -1
- package/src/rules/sortedImports/ImportGroupOrder.ts +2 -1
- package/src/rules/sortedImports/areSpecifiersSorted.ts +1 -1
- package/src/rules/sortedImports/categorizeImport.ts +4 -0
- package/src/rules/sortedImports/checkAlphabeticalSorting.ts +1 -1
- package/src/rules/sortedImports/createFix/buildSortedCode.ts +2 -1
- package/src/rules/sortedImports/createFix/formatNamedImport.ts +3 -2
- package/src/rules/sortedImports/createFix/getReplacementRange.ts +3 -3
- package/src/rules/sortedImports/createFix/groupImportsByType.ts +1 -0
- package/src/rules/sortedImports/createFix/index.ts +10 -11
- package/src/rules/sortedImports/createFix/sortImportGroups.ts +2 -1
- package/src/rules/sortedImports/getSortKey.ts +8 -2
- package/src/rules/sortedImports/index.ts +8 -5
- package/src/rules/sortedImports/sortSpecifiersText.ts +4 -3
- package/src/rules/sortedReExports/CategorizedReExport.ts +14 -3
- package/src/rules/sortedReExports/ReExportError.ts +5 -2
- package/src/rules/sortedReExports/ReExportGroup.ts +1 -0
- package/src/rules/sortedReExports/ReExportGroupOrder.ts +2 -1
- package/src/rules/sortedReExports/areSpecifiersSorted.ts +1 -1
- package/src/rules/sortedReExports/categorizeReExport.ts +8 -4
- package/src/rules/sortedReExports/categorizeReExports.ts +1 -1
- package/src/rules/sortedReExports/checkAlphabeticalSorting.ts +1 -1
- package/src/rules/sortedReExports/createFix/buildSortedCode.ts +2 -1
- package/src/rules/sortedReExports/createFix/formatNamedReExport.ts +3 -2
- package/src/rules/sortedReExports/createFix/getReplacementRange.ts +1 -1
- package/src/rules/sortedReExports/createFix/groupReExportsByType.ts +1 -0
- package/src/rules/sortedReExports/createFix/index.ts +10 -11
- package/src/rules/sortedReExports/createFix/sortExportGroups.ts +2 -1
- package/src/rules/sortedReExports/getNamedSpecifiers.ts +1 -1
- package/src/rules/sortedReExports/getReExportGroups.ts +1 -1
- package/src/rules/sortedReExports/getSortKey.ts +11 -5
- package/src/rules/sortedReExports/index.ts +8 -5
- package/src/rules/sortedReExports/isNamedReExport.ts +2 -2
- package/src/rules/sortedReExports/sortSpecifiersText.ts +4 -3
- package/src/rules/importsAndReExportsAtTop/ReExport.ts +0 -5
- /package/src/{rules/sortedReExports → lib}/ReExportDeclaration.ts +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {formatNamed} from './formatNamed'
|
|
2
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
3
|
+
import type {TSESTree} from '@typescript-eslint/utils'
|
|
4
|
+
|
|
5
|
+
export function formatSpecifiers(
|
|
6
|
+
declaration: TSESTree.ImportDeclaration,
|
|
7
|
+
sourceCode: TSESLint.SourceCode,
|
|
8
|
+
): string {
|
|
9
|
+
const defaultSpecifier = declaration.specifiers.find(
|
|
10
|
+
(s): s is TSESTree.ImportDefaultSpecifier => s.type === 'ImportDefaultSpecifier',
|
|
11
|
+
)
|
|
12
|
+
const namespaceSpecifier = declaration.specifiers.find(
|
|
13
|
+
(s): s is TSESTree.ImportNamespaceSpecifier => s.type === 'ImportNamespaceSpecifier',
|
|
14
|
+
)
|
|
15
|
+
const namedSpecifiers = declaration.specifiers.filter(
|
|
16
|
+
(s): s is TSESTree.ImportSpecifier => s.type === 'ImportSpecifier',
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if (namespaceSpecifier)
|
|
20
|
+
return `* as ${namespaceSpecifier.local.name}`
|
|
21
|
+
|
|
22
|
+
if (defaultSpecifier && namedSpecifiers.length > 0)
|
|
23
|
+
return `${defaultSpecifier.local.name}, {${formatNamed(namedSpecifiers, sourceCode)}}`
|
|
24
|
+
|
|
25
|
+
if (defaultSpecifier)
|
|
26
|
+
return defaultSpecifier.local.name
|
|
27
|
+
|
|
28
|
+
if (namedSpecifiers.length === 0)
|
|
29
|
+
return ''
|
|
30
|
+
|
|
31
|
+
return `{${formatNamed(namedSpecifiers, sourceCode)}}`
|
|
32
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {createFix} from './createFix'
|
|
2
|
+
import {isMultiline} from './isMultiline'
|
|
3
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
4
|
+
|
|
5
|
+
type MessageIds = 'multiline'
|
|
6
|
+
|
|
7
|
+
export const singleLineImports: TSESLint.RuleModule<MessageIds, []> = {
|
|
8
|
+
meta: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: 'Enforce imports to be on a single line',
|
|
11
|
+
},
|
|
12
|
+
fixable: 'code',
|
|
13
|
+
messages: {
|
|
14
|
+
multiline: 'Import should be on a single line',
|
|
15
|
+
},
|
|
16
|
+
schema: [],
|
|
17
|
+
type: 'layout',
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
create(context) {
|
|
21
|
+
return {
|
|
22
|
+
ImportDeclaration(node) {
|
|
23
|
+
if (!isMultiline(node))
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
context.report({
|
|
27
|
+
node,
|
|
28
|
+
messageId: 'multiline',
|
|
29
|
+
fix: fixer => createFix(fixer, node, context.sourceCode),
|
|
30
|
+
})
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {formatAttributes} from '../singleLineImports/formatAttributes'
|
|
2
|
+
import type {ReExportDeclaration} from '@lib/ReExportDeclaration'
|
|
3
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
4
|
+
|
|
5
|
+
export function createFix(
|
|
6
|
+
fixer: TSESLint.RuleFixer,
|
|
7
|
+
declaration: ReExportDeclaration,
|
|
8
|
+
sourceCode: TSESLint.SourceCode,
|
|
9
|
+
): TSESLint.RuleFix {
|
|
10
|
+
const source = declaration.source!.value
|
|
11
|
+
|
|
12
|
+
if (declaration.type === 'ExportAllDeclaration') {
|
|
13
|
+
const exported = declaration.exported
|
|
14
|
+
? `* as ${sourceCode.getText(declaration.exported)}`
|
|
15
|
+
: '*'
|
|
16
|
+
const attributes = formatAttributes(declaration.attributes)
|
|
17
|
+
const result = `export ${exported} from '${source}'${attributes}`
|
|
18
|
+
return fixer.replaceText(declaration, result)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const prefix = declaration.exportKind === 'type' ? 'export type ' : 'export '
|
|
22
|
+
const specifiers = declaration.specifiers.map(
|
|
23
|
+
s => sourceCode.getText(s),
|
|
24
|
+
).join(', ')
|
|
25
|
+
const attributes = formatAttributes(declaration.attributes)
|
|
26
|
+
const result = `${prefix}{${specifiers}} from '${source}'${attributes}`
|
|
27
|
+
|
|
28
|
+
return fixer.replaceText(declaration, result)
|
|
29
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {createFix} from './createFix'
|
|
2
|
+
import {isMultiline} from './isMultiline'
|
|
3
|
+
import type {ReExportDeclaration} from '@lib/ReExportDeclaration'
|
|
4
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
5
|
+
import type {TSESTree} from '@typescript-eslint/utils'
|
|
6
|
+
|
|
7
|
+
type MessageIds = 'multiline'
|
|
8
|
+
|
|
9
|
+
export const singleLineReExports: TSESLint.RuleModule<MessageIds, []> = {
|
|
10
|
+
meta: {
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Enforce re-exports to be on a single line',
|
|
13
|
+
},
|
|
14
|
+
fixable: 'code',
|
|
15
|
+
messages: {
|
|
16
|
+
multiline: 'Re-export should be on a single line',
|
|
17
|
+
},
|
|
18
|
+
schema: [],
|
|
19
|
+
type: 'layout',
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
create(context) {
|
|
23
|
+
const checkDeclaration = (
|
|
24
|
+
node: TSESTree.Node,
|
|
25
|
+
declaration: ReExportDeclaration,
|
|
26
|
+
) => {
|
|
27
|
+
// Skip local exports (only process re-exports with a source)
|
|
28
|
+
if (!declaration.source)
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
if (!isMultiline(declaration))
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
context.report({
|
|
35
|
+
node,
|
|
36
|
+
messageId: 'multiline',
|
|
37
|
+
fix: fixer => createFix(fixer, declaration, context.sourceCode),
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
ExportNamedDeclaration: node =>
|
|
43
|
+
checkDeclaration(node, node),
|
|
44
|
+
ExportAllDeclaration: node =>
|
|
45
|
+
checkDeclaration(node, node),
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
}
|
|
@@ -10,6 +10,10 @@ export function categorizeImport(declaration: TSESTree.ImportDeclaration): Impor
|
|
|
10
10
|
if (declaration.specifiers.length === 0)
|
|
11
11
|
return 'side-effect'
|
|
12
12
|
|
|
13
|
+
// Example: import * as fs from 'module'
|
|
14
|
+
if (declaration.specifiers.some(s => s.type === 'ImportNamespaceSpecifier'))
|
|
15
|
+
return 'namespace'
|
|
16
|
+
|
|
13
17
|
// Example: import value from 'module'
|
|
14
18
|
if (declaration.specifiers.some(s => s.type === 'ImportDefaultSpecifier'))
|
|
15
19
|
return 'default'
|
|
@@ -2,10 +2,11 @@ import {formatNamedImport} from './formatNamedImport'
|
|
|
2
2
|
import {importGroupOrder} from '../ImportGroupOrder'
|
|
3
3
|
import type {CategorizedImport} from '../CategorizedImport'
|
|
4
4
|
import type {ImportGroup} from '../ImportGroup'
|
|
5
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
5
6
|
|
|
6
7
|
export function buildSortedCode(
|
|
7
8
|
grouped: Record<ImportGroup, CategorizedImport[]>,
|
|
8
|
-
sourceCode:
|
|
9
|
+
sourceCode: TSESLint.SourceCode,
|
|
9
10
|
): string[] {
|
|
10
11
|
const sortedCode: string[] = []
|
|
11
12
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {areSpecifiersSorted} from '../areSpecifiersSorted'
|
|
2
2
|
import {getNamedSpecifiers} from '../getNamedSpecifiers'
|
|
3
3
|
import {sortSpecifiersText} from '../sortSpecifiersText'
|
|
4
|
-
import type {
|
|
4
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
5
|
+
import type {TSESTree} from '@typescript-eslint/utils'
|
|
5
6
|
|
|
6
7
|
export function formatNamedImport(
|
|
7
8
|
declaration: TSESTree.ImportDeclaration,
|
|
8
|
-
sourceCode:
|
|
9
|
+
sourceCode: TSESLint.SourceCode,
|
|
9
10
|
): string {
|
|
10
11
|
const specifiers = getNamedSpecifiers(declaration)
|
|
11
12
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {findLastImportIndex} from './findLastImportIndex'
|
|
2
|
-
import type {ReplacementRange} from '
|
|
2
|
+
import type {ReplacementRange} from '@lib/ReplacementRange'
|
|
3
3
|
import type {TSESTree} from '@typescript-eslint/types'
|
|
4
4
|
|
|
5
5
|
export function getReplacementRange(
|
|
6
6
|
programBody: TSESTree.ProgramStatement[],
|
|
7
7
|
): ReplacementRange {
|
|
8
8
|
const lastIndex = findLastImportIndex(programBody)
|
|
9
|
-
const firstImport = programBody[0]
|
|
10
|
-
const lastImport = programBody[lastIndex]
|
|
9
|
+
const firstImport = programBody[0]
|
|
10
|
+
const lastImport = programBody[lastIndex]
|
|
11
11
|
const start = firstImport.range![0]
|
|
12
12
|
const end = lastImport.range![1]
|
|
13
13
|
return {start, end}
|
|
@@ -2,17 +2,16 @@ import {buildSortedCode} from './buildSortedCode'
|
|
|
2
2
|
import {categorizeImports} from '../categorizeImports'
|
|
3
3
|
import {groupImportsByType} from './groupImportsByType'
|
|
4
4
|
import {sortImportGroups} from './sortImportGroups'
|
|
5
|
-
import type {
|
|
6
|
-
import type {TSESTree} from '@typescript-eslint/
|
|
5
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
6
|
+
import type {TSESTree} from '@typescript-eslint/utils'
|
|
7
7
|
|
|
8
8
|
function createFixForGroup(
|
|
9
|
-
fixer:
|
|
9
|
+
fixer: TSESLint.RuleFixer,
|
|
10
10
|
importDeclarations: TSESTree.ImportDeclaration[],
|
|
11
|
-
sourceCode:
|
|
12
|
-
)
|
|
13
|
-
if (importDeclarations.length === 0)
|
|
11
|
+
sourceCode: TSESLint.SourceCode,
|
|
12
|
+
) {
|
|
13
|
+
if (importDeclarations.length === 0)
|
|
14
14
|
return null
|
|
15
|
-
}
|
|
16
15
|
|
|
17
16
|
const categorized = categorizeImports(importDeclarations)
|
|
18
17
|
const grouped = groupImportsByType(categorized)
|
|
@@ -32,11 +31,11 @@ function createFixForGroup(
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export function createFix(
|
|
35
|
-
fixer:
|
|
34
|
+
fixer: TSESLint.RuleFixer,
|
|
36
35
|
importGroups: TSESTree.ImportDeclaration[][],
|
|
37
|
-
sourceCode:
|
|
38
|
-
):
|
|
39
|
-
const fixes:
|
|
36
|
+
sourceCode: TSESLint.SourceCode,
|
|
37
|
+
): TSESLint.RuleFix[] {
|
|
38
|
+
const fixes: TSESLint.RuleFix[] = []
|
|
40
39
|
|
|
41
40
|
for (const group of importGroups) {
|
|
42
41
|
const fix = createFixForGroup(fixer, group, sourceCode)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {compare} from '
|
|
1
|
+
import {compare} from '@lib/compare'
|
|
2
2
|
import type {CategorizedImport} from '../CategorizedImport'
|
|
3
3
|
import type {ImportGroup} from '../ImportGroup'
|
|
4
4
|
|
|
@@ -6,6 +6,7 @@ export function sortImportGroups(
|
|
|
6
6
|
grouped: Record<ImportGroup, CategorizedImport[]>,
|
|
7
7
|
): void {
|
|
8
8
|
grouped['side-effect'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
9
|
+
grouped['namespace'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
9
10
|
grouped['default'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
10
11
|
grouped['named'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
11
12
|
grouped['type'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
@@ -7,11 +7,17 @@ export function getSortKey(declaration: TSESTree.ImportDeclaration): string {
|
|
|
7
7
|
if (group === 'side-effect')
|
|
8
8
|
return declaration.source.value
|
|
9
9
|
|
|
10
|
+
if (group === 'namespace') {
|
|
11
|
+
const namespaceSpecifier = declaration.specifiers.find(
|
|
12
|
+
s => s.type === 'ImportNamespaceSpecifier',
|
|
13
|
+
)
|
|
14
|
+
return `*${namespaceSpecifier?.local.name ?? ''}`
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
if (group === 'default') {
|
|
11
18
|
const defaultSpecifier = declaration.specifiers.find(
|
|
12
19
|
s => s.type === 'ImportDefaultSpecifier',
|
|
13
|
-
)
|
|
14
|
-
|
|
20
|
+
)
|
|
15
21
|
return defaultSpecifier?.local.name ?? ''
|
|
16
22
|
}
|
|
17
23
|
|
|
@@ -5,14 +5,17 @@ import {checkSpecifiersSorting} from './checkSpecifiersSorting'
|
|
|
5
5
|
import {createFix} from './createFix'
|
|
6
6
|
import {getImportGroups} from './getImportGroups'
|
|
7
7
|
import type {ImportError} from './ImportError'
|
|
8
|
-
import type {
|
|
9
|
-
import type {TSESTree} from '@typescript-eslint/types'
|
|
8
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
type MessageIds =
|
|
11
|
+
| 'sortedImports'
|
|
12
|
+
| 'sortedNames'
|
|
13
|
+
| 'wrongGroup'
|
|
14
|
+
|
|
15
|
+
export const sortedImports: TSESLint.RuleModule<MessageIds, []> = {
|
|
12
16
|
meta: {
|
|
13
17
|
docs: {
|
|
14
18
|
description: 'Enforce sorted imports alphabetically',
|
|
15
|
-
recommended: true,
|
|
16
19
|
},
|
|
17
20
|
fixable: 'code',
|
|
18
21
|
messages: {
|
|
@@ -26,7 +29,7 @@ export const sortedImports: Rule.RuleModule = {
|
|
|
26
29
|
create(context) {
|
|
27
30
|
return {
|
|
28
31
|
Program(node) {
|
|
29
|
-
const body = node.body
|
|
32
|
+
const body = node.body
|
|
30
33
|
const importGroups = getImportGroups(body)
|
|
31
34
|
if (importGroups.length === 0)
|
|
32
35
|
return
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {compare} from '
|
|
1
|
+
import {compare} from '@lib/compare'
|
|
2
2
|
import {getSpecifierName} from './getSpecifierName'
|
|
3
|
-
import type {
|
|
3
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
4
|
+
import type {TSESTree} from '@typescript-eslint/utils'
|
|
4
5
|
|
|
5
6
|
export function sortSpecifiersText(
|
|
6
7
|
specifiers: TSESTree.ImportSpecifier[],
|
|
7
|
-
sourceCode:
|
|
8
|
+
sourceCode: TSESLint.SourceCode,
|
|
8
9
|
): string {
|
|
9
10
|
const sorted = [...specifiers].sort((a, b) => {
|
|
10
11
|
const nameA = getSpecifierName(a)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {TSESTree} from '@typescript-eslint/types'
|
|
1
|
+
import type {TSESTree} from '@typescript-eslint/types'
|
|
2
2
|
|
|
3
3
|
interface NamedReExport {
|
|
4
4
|
declaration: TSESTree.ExportNamedDeclaration
|
|
5
|
-
group:
|
|
5
|
+
group:
|
|
6
|
+
| 're-export-named'
|
|
7
|
+
| 're-export-type'
|
|
6
8
|
sortKey: string
|
|
7
9
|
}
|
|
8
10
|
|
|
@@ -12,4 +14,13 @@ interface ReExportAll {
|
|
|
12
14
|
sortKey: string
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
interface ReExportNamespace {
|
|
18
|
+
declaration: TSESTree.ExportAllDeclaration
|
|
19
|
+
group: 're-export-namespace'
|
|
20
|
+
sortKey: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type CategorizedReExport =
|
|
24
|
+
| NamedReExport
|
|
25
|
+
| ReExportAll
|
|
26
|
+
| ReExportNamespace
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type {ReExportDeclaration} from '
|
|
1
|
+
import type {ReExportDeclaration} from '@lib/ReExportDeclaration'
|
|
2
2
|
|
|
3
3
|
export interface ReExportError {
|
|
4
4
|
node: ReExportDeclaration
|
|
5
|
-
messageId:
|
|
5
|
+
messageId:
|
|
6
|
+
| 'sortedReExports'
|
|
7
|
+
| 'sortedNames'
|
|
8
|
+
| 'wrongGroup'
|
|
6
9
|
}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import type {ReExportDeclaration} from '@lib/ReExportDeclaration'
|
|
1
2
|
import type {ReExportGroup} from './ReExportGroup'
|
|
2
|
-
import type {TSESTree} from '@typescript-eslint/types'
|
|
3
3
|
|
|
4
4
|
export function categorizeReExport(
|
|
5
|
-
declaration:
|
|
5
|
+
declaration: ReExportDeclaration,
|
|
6
6
|
): ReExportGroup {
|
|
7
|
-
// Example: export * from 'module'
|
|
8
|
-
if (declaration.type === 'ExportAllDeclaration')
|
|
7
|
+
// Example: export * from 'module' or export * as ns from 'module'
|
|
8
|
+
if (declaration.type === 'ExportAllDeclaration') {
|
|
9
|
+
// Export * as ns from 'module' has an 'exported' property
|
|
10
|
+
if (declaration.exported)
|
|
11
|
+
return 're-export-namespace'
|
|
9
12
|
return 're-export-all'
|
|
13
|
+
}
|
|
10
14
|
|
|
11
15
|
// Example: export type {Type} from 'module'
|
|
12
16
|
if (declaration.exportKind === 'type')
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {categorizeReExport} from './categorizeReExport'
|
|
2
2
|
import {getSortKey} from './getSortKey'
|
|
3
|
-
import {ReExportDeclaration} from './ReExportDeclaration'
|
|
4
3
|
import type {CategorizedReExport} from './CategorizedReExport'
|
|
4
|
+
import type {ReExportDeclaration} from '@lib/ReExportDeclaration'
|
|
5
5
|
|
|
6
6
|
export function categorizeReExports(declarations: ReExportDeclaration[]): CategorizedReExport[] {
|
|
7
7
|
return declarations.map(declaration => {
|
|
@@ -3,10 +3,11 @@ import {isNamedReExport} from '../isNamedReExport'
|
|
|
3
3
|
import {reExportGroupOrder} from '../ReExportGroupOrder'
|
|
4
4
|
import type {CategorizedReExport} from '../CategorizedReExport'
|
|
5
5
|
import type {ReExportGroup} from '../ReExportGroup'
|
|
6
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
6
7
|
|
|
7
8
|
export function buildSortedCode(
|
|
8
9
|
grouped: Record<ReExportGroup, CategorizedReExport[]>,
|
|
9
|
-
sourceCode:
|
|
10
|
+
sourceCode: TSESLint.SourceCode,
|
|
10
11
|
): string[] {
|
|
11
12
|
const sortedCode: string[] = []
|
|
12
13
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {areSpecifiersSorted} from '../areSpecifiersSorted'
|
|
2
2
|
import {getNamedSpecifiers} from '../getNamedSpecifiers'
|
|
3
3
|
import {sortSpecifiersText} from '../sortSpecifiersText'
|
|
4
|
-
import type {
|
|
4
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
5
|
+
import type {TSESTree} from '@typescript-eslint/utils'
|
|
5
6
|
|
|
6
7
|
export function formatNamedReExport(
|
|
7
8
|
declaration: TSESTree.ExportNamedDeclaration,
|
|
8
|
-
sourceCode:
|
|
9
|
+
sourceCode: TSESLint.SourceCode,
|
|
9
10
|
): string {
|
|
10
11
|
const specifiers = getNamedSpecifiers(declaration)
|
|
11
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {findFirstExportIndex} from './findFirstExportIndex'
|
|
2
2
|
import {findLastExportIndex} from './findLastExportIndex'
|
|
3
|
-
import type {ReplacementRange} from '
|
|
3
|
+
import type {ReplacementRange} from '@lib/ReplacementRange'
|
|
4
4
|
import type {TSESTree} from '@typescript-eslint/types'
|
|
5
5
|
|
|
6
6
|
export function getReplacementRange(
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import {buildSortedCode} from './buildSortedCode'
|
|
2
2
|
import {categorizeReExports} from '../categorizeReExports'
|
|
3
3
|
import {groupReExportsByType} from './groupReExportsByType'
|
|
4
|
-
import {ReExportDeclaration} from '../ReExportDeclaration'
|
|
5
4
|
import {sortExportGroups} from './sortExportGroups'
|
|
6
|
-
import type {
|
|
5
|
+
import type {ReExportDeclaration} from '@lib/ReExportDeclaration'
|
|
6
|
+
import type {TSESLint} from '@typescript-eslint/utils'
|
|
7
7
|
|
|
8
8
|
function createFixForGroup(
|
|
9
|
-
fixer:
|
|
9
|
+
fixer: TSESLint.RuleFixer,
|
|
10
10
|
reExportDeclarations: ReExportDeclaration[],
|
|
11
|
-
sourceCode:
|
|
12
|
-
)
|
|
13
|
-
if (reExportDeclarations.length === 0)
|
|
11
|
+
sourceCode: TSESLint.SourceCode,
|
|
12
|
+
) {
|
|
13
|
+
if (reExportDeclarations.length === 0)
|
|
14
14
|
return null
|
|
15
|
-
}
|
|
16
15
|
|
|
17
16
|
const categorized = categorizeReExports(reExportDeclarations)
|
|
18
17
|
const grouped = groupReExportsByType(categorized)
|
|
@@ -32,11 +31,11 @@ function createFixForGroup(
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export function createFix(
|
|
35
|
-
fixer:
|
|
34
|
+
fixer: TSESLint.RuleFixer,
|
|
36
35
|
reExportGroups: ReExportDeclaration[][],
|
|
37
|
-
sourceCode:
|
|
38
|
-
):
|
|
39
|
-
const fixes:
|
|
36
|
+
sourceCode: TSESLint.SourceCode,
|
|
37
|
+
): TSESLint.RuleFix[] {
|
|
38
|
+
const fixes: TSESLint.RuleFix[] = []
|
|
40
39
|
|
|
41
40
|
for (const group of reExportGroups) {
|
|
42
41
|
const fix = createFixForGroup(fixer, group, sourceCode)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {compare} from '
|
|
1
|
+
import {compare} from '@lib/compare'
|
|
2
2
|
import type {CategorizedReExport} from '../CategorizedReExport'
|
|
3
3
|
import type {ReExportGroup} from '../ReExportGroup'
|
|
4
4
|
|
|
@@ -6,6 +6,7 @@ export function sortExportGroups(
|
|
|
6
6
|
grouped: Record<ReExportGroup, CategorizedReExport[]>,
|
|
7
7
|
): void {
|
|
8
8
|
grouped['re-export-all'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
9
|
+
grouped['re-export-namespace'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
9
10
|
grouped['re-export-named'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
10
11
|
grouped['re-export-type'].sort((a, b) => compare(a.sortKey, b.sortKey))
|
|
11
12
|
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {categorizeReExport} from './categorizeReExport'
|
|
2
|
+
import type {ReExportDeclaration} from '@lib/ReExportDeclaration'
|
|
2
3
|
|
|
3
|
-
export function getSortKey(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (declaration.type === 'ExportAllDeclaration')
|
|
4
|
+
export function getSortKey(declaration: ReExportDeclaration): string {
|
|
5
|
+
const group = categorizeReExport(declaration)
|
|
6
|
+
|
|
7
|
+
if (declaration.type === 'ExportAllDeclaration') {
|
|
8
|
+
if (group === 're-export-namespace') {
|
|
9
|
+
if (declaration.exported?.type === 'Identifier')
|
|
10
|
+
return `*${declaration.exported.name}`
|
|
11
|
+
}
|
|
7
12
|
return declaration.source.value
|
|
13
|
+
}
|
|
8
14
|
|
|
9
15
|
const specifier = declaration.specifiers[0]
|
|
10
16
|
if (!specifier)
|