Skip to content

Commit bc4de89

Browse files
authored
test: migrate to type-friendly createRuleTestCaseFunction (#184)
1 parent 8c1c14d commit bc4de89

File tree

69 files changed

+4414
-4931
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+4414
-4931
lines changed

.changeset/cuddly-ligers-wonder.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-import-x": patch
3+
---
4+
5+
fix(no-cycle): improves the type declaration of the rule `no-cycle`’s `maxDepth` option

.changeset/fluffy-dolls-pump.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-import-x": patch
3+
---
4+
5+
fix(first): improves the type declaration of the rule `first`'s option

.changeset/nice-schools-drive.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-import-x": patch
3+
---
4+
5+
fix(no-unused-modules): improves the type declaration of the rule `no-unused-modules`’s `missingExports` option

.changeset/nine-wolves-repeat.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-import-x": patch
3+
---
4+
5+
fix(no-deprecated): improve error message when no description is available

.eslintrc.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
module.exports = {
55
root: true,
6+
reportUnusedDisableDirectives: true,
67
extends: [
78
'eslint:recommended',
89
'plugin:@typescript-eslint/recommended',
@@ -33,7 +34,7 @@ module.exports = {
3334
'eslint-plugin/report-message-format': 'error',
3435
'eslint-plugin/require-meta-docs-description': [
3536
'error',
36-
{ pattern: '^(Enforce|Ensure|Prefer|Forbid).+\\.$' },
37+
{ pattern: String.raw`^(Enforce|Ensure|Prefer|Forbid).+\.$` },
3738
],
3839
'eslint-plugin/require-meta-schema': 'error',
3940
'eslint-plugin/require-meta-type': 'error',

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"eslint": "^8.57.0 || ^9.0.0"
4949
},
5050
"dependencies": {
51+
"@typescript-eslint/scope-manager": "^8.1.0",
5152
"@typescript-eslint/utils": "^8.1.0",
5253
"debug": "^4.3.4",
5354
"doctrine": "^3.0.0",
@@ -82,8 +83,8 @@
8283
"@total-typescript/ts-reset": "^0.5.1",
8384
"@types/debug": "^4.1.12",
8485
"@types/doctrine": "^0.0.9",
85-
"@types/eslint8.56": "npm:@types/eslint@^8.56.11",
8686
"@types/eslint": "^9.6.1",
87+
"@types/eslint8.56": "npm:@types/eslint@^8.56.11",
8788
"@types/eslint9": "npm:@types/eslint@^9.6.1",
8889
"@types/is-glob": "^4.0.4",
8990
"@types/jest": "^29.5.12",
@@ -97,9 +98,7 @@
9798
"cross-env": "^7.0.3",
9899
"enhanced-resolve": "^5.16.0",
99100
"escope": "^4.0.0",
100-
"eslint8.56": "npm:eslint@^8.56.0",
101101
"eslint": "^9.15.0",
102-
"eslint9": "npm:eslint@^9.15.0",
103102
"eslint-config-prettier": "^9.1.0",
104103
"eslint-doc-generator": "^1.7.1",
105104
"eslint-import-resolver-typescript": "^3.6.1",
@@ -112,6 +111,8 @@
112111
"eslint-plugin-n": "^16.6.2",
113112
"eslint-plugin-prettier": "^5.1.3",
114113
"eslint-plugin-unicorn": "^56.0.1",
114+
"eslint8.56": "npm:eslint@^8.56.0",
115+
"eslint9": "npm:eslint@^9.15.0",
115116
"hermes-eslint": "^0.23.1",
116117
"jest": "^29.7.0",
117118
"klaw-sync": "^6.0.0",

src/rules/dynamic-import-chunkname.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export = createRule<[Options?], MessageId>({
7373
const {
7474
importFunctions = [],
7575
allowEmpty = false,
76-
webpackChunknameFormat = '([0-9a-zA-Z-_/.]|\\[(request|index)\\])+',
76+
webpackChunknameFormat = String.raw`([0-9a-zA-Z-_/.]|\[(request|index)\])+`,
7777
} = context.options[0] || {}
7878

7979
const paddedCommentRegex = /^ (\S[\S\s]+\S) $/

src/rules/first.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ function isPossibleDirective(node: TSESTree.ProgramStatement) {
2020
)
2121
}
2222

23+
type Options = 'absolute-first' | 'disable-absolute-first'
24+
2325
type MessageId = 'absolute' | 'order'
2426

25-
export = createRule<['absolute-first'?], MessageId>({
27+
export = createRule<[Options?], MessageId>({
2628
name: 'first',
2729
meta: {
2830
type: 'suggestion',

src/rules/group-exports.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ function accessorChain(node: TSESTree.MemberExpression) {
3535
return chain
3636
}
3737

38-
export = createRule<[], 'ExportNamedDeclaration' | 'AssignmentExpression'>({
38+
type MessageId = 'ExportNamedDeclaration' | 'AssignmentExpression'
39+
40+
export = createRule<[], MessageId>({
3941
name: 'group-exports',
4042
meta: {
4143
type: 'suggestion',

src/rules/namespace.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type MessageId =
1515
| 'namespaceMember'
1616
| 'topLevelNames'
1717
| 'notFoundInNamespace'
18+
| 'notFoundInNamespaceDeep'
1819

1920
type Options = {
2021
allowComputed?: boolean
@@ -86,15 +87,16 @@ function makeMessage(
8687
namepath: string[],
8788
node: TSESTree.Node = last,
8889
) {
90+
const messageId =
91+
namepath.length > 1 ? 'notFoundInNamespaceDeep' : 'notFoundInNamespace'
8992
return {
9093
node,
91-
messageId: 'notFoundInNamespace' as const,
94+
messageId,
9295
data: {
9396
name: last.name,
94-
depth: namepath.length > 1 ? 'deeply ' : '',
9597
namepath: namepath.join('.'),
9698
},
97-
}
99+
} as const
98100
}
99101

100102
export = createRule<[Options], MessageId>({
@@ -127,7 +129,9 @@ export = createRule<[Options], MessageId>({
127129
namespaceMember: "Assignment to member of namespace '{{namespace}}'.",
128130
topLevelNames: 'Only destructure top-level names.',
129131
notFoundInNamespace:
130-
"'{{name}}' not found in {{depth}}imported namespace '{{namepath}}'.",
132+
"'{{name}}' not found in imported namespace '{{namepath}}'.",
133+
notFoundInNamespaceDeep:
134+
"'{{name}}' not found in deeply imported namespace '{{namepath}}'.",
131135
},
132136
},
133137
defaultOptions: [

src/rules/no-cycle.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ import {
1515
type Options = {
1616
allowUnsafeDynamicCyclicDependency?: boolean
1717
ignoreExternal?: boolean
18-
maxDepth?: number
18+
maxDepth?: number | '∞'
1919
} & ModuleOptions
2020

21-
type MessageId = 'cycle'
21+
type MessageId = 'cycle' | 'cycleSource'
2222

2323
type Traverser = {
2424
mget(): ExportMap | null
@@ -65,7 +65,8 @@ export = createRule<[Options?], MessageId>({
6565
}),
6666
],
6767
messages: {
68-
cycle: 'Dependency cycle {{source}}',
68+
cycle: 'Dependency cycle detected',
69+
cycleSource: 'Dependency cycle via "{{source}}"',
6970
},
7071
},
7172
defaultOptions: [],
@@ -187,16 +188,20 @@ export = createRule<[Options?], MessageId>({
187188
while (untraversed.length > 0) {
188189
const next = untraversed.shift()! // bfs!
189190
if (detectCycle(next)) {
190-
context.report({
191-
node: importer,
192-
messageId: 'cycle',
193-
data: {
194-
source:
195-
next.route.length > 0
196-
? `via ${routeString(next.route)}`
197-
: 'detected.',
198-
},
199-
})
191+
if (next.route.length > 0) {
192+
context.report({
193+
node: importer,
194+
messageId: 'cycleSource',
195+
data: {
196+
source: routeString(next.route),
197+
},
198+
})
199+
} else {
200+
context.report({
201+
node: importer,
202+
messageId: 'cycle',
203+
})
204+
}
200205
return
201206
}
202207
}

src/rules/no-default-export.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ export = createRule({
3737

3838
ExportNamedDeclaration(node) {
3939
for (const specifier of node.specifiers.filter(
40-
specifier => getValue(specifier.exported) === 'default')) {
40+
specifier => getValue(specifier.exported) === 'default',
41+
)) {
4142
const { loc } = sourceCode.getFirstTokens(node)[1] || {}
4243
// @ts-expect-error - experimental parser type
4344
if (specifier.type === 'ExportDefaultSpecifier') {

src/rules/no-deprecated.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import type { ModuleNamespace } from '../utils'
55
import { ExportMap, createRule, declaredScope, getValue } from '../utils'
66

77
function message(deprecation: Tag) {
8-
return {
9-
messageId: 'deprecated',
10-
data: {
11-
description: deprecation.description
12-
? `: ${deprecation.description}`
13-
: '.',
14-
},
15-
} as const
8+
if (deprecation.description) {
9+
return {
10+
messageId: 'deprecatedDesc',
11+
data: { description: deprecation.description },
12+
} as const
13+
}
14+
15+
return { messageId: 'deprecated' } as const
1616
}
1717

1818
function getDeprecation(metadata?: ModuleNamespace | null) {
@@ -34,7 +34,8 @@ export = createRule({
3434
},
3535
schema: [],
3636
messages: {
37-
deprecated: 'Deprecated{{description}}',
37+
deprecatedDesc: 'Deprecated: {{description}}',
38+
deprecated: 'Deprecated: consider to find an alternative.',
3839
},
3940
},
4041
defaultOptions: [],

src/rules/no-duplicates.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ function hasCommentInsideNonSpecifiers(
381381
// `node` (only inside). If there's a `{...}` part, look for comments before
382382
// the `{`, but not before the `}` (hence the `+1`s).
383383
const someTokens =
384-
openBraceIndex >= 0 && closeBraceIndex >= 0
384+
openBraceIndex !== -1 && closeBraceIndex !== -1
385385
? [
386386
...tokens.slice(1, openBraceIndex + 1),
387387
...tokens.slice(closeBraceIndex + 1),

src/rules/no-import-module-exports.ts

+9-11
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@ function getEntryPoint(context: RuleContext) {
2121

2222
function findScope(context: RuleContext, identifier: string) {
2323
const { scopeManager } = context.sourceCode
24-
return (
25-
scopeManager?.scopes
26-
// eslint-disable-next-line unicorn/prefer-spread
27-
.slice()
28-
.reverse()
29-
.find(scope =>
30-
scope.variables.some(variable =>
31-
variable.identifiers.some(node => node.name === identifier),
32-
),
33-
)
34-
)
24+
return scopeManager?.scopes
25+
26+
.slice()
27+
.reverse()
28+
.find(scope =>
29+
scope.variables.some(variable =>
30+
variable.identifiers.some(node => node.name === identifier),
31+
),
32+
)
3533
}
3634

3735
function findDefinition(objectScope: TSESLint.Scope.Scope, identifier: string) {

src/rules/no-named-export.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ export = createRule({
3232
}
3333

3434
const someNamed = node.specifiers.some(
35-
specifier => getValue(specifier.exported) !==
36-
'default',
35+
specifier => getValue(specifier.exported) !== 'default',
3736
)
3837
if (someNamed) {
3938
context.report({ node, messageId: 'noAllowed' })

src/rules/no-unused-modules.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ const fileIsInPkg = (file: string) => {
391391
type Options = {
392392
src?: string[]
393393
ignoreExports?: string[]
394-
missingExports?: string[]
394+
missingExports?: true
395395
unusedExports?: boolean
396396
ignoreUnusedTypeExports?: boolean
397397
}

src/rules/prefer-default-export.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,7 @@ export = createRule<[Options?], MessageId>({
6969
},
7070

7171
ExportSpecifier(node) {
72-
if (
73-
getValue(node.exported) === 'default'
74-
) {
72+
if (getValue(node.exported) === 'default') {
7573
hasDefaultExport = true
7674
} else {
7775
specifierExportCount++

src/utils/declared-scope.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import type { ScopeType } from '@typescript-eslint/scope-manager'
12
import type { TSESTree } from '@typescript-eslint/utils'
2-
import type { ScopeType } from '@typescript-eslint/scope-manager';
33

44
import type { RuleContext } from '../types'
55

src/utils/export-map.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,10 @@ export class ExportMap {
241241
}
242242
}
243243

244-
function addNamespace(object: object, identifier: TSESTree.Identifier | TSESTree.StringLiteral) {
244+
function addNamespace(
245+
object: object,
246+
identifier: TSESTree.Identifier | TSESTree.StringLiteral,
247+
) {
245248
const nsfn = getNamespace(getValue(identifier))
246249
if (nsfn) {
247250
Object.defineProperty(object, 'namespace', { get: nsfn })

src/utils/pkg-up.ts

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ function findUp(filename: string | string[], cwd?: string): string | null {
77

88
const filenames = [filename].flat()
99

10-
// eslint-disable-next-line no-constant-condition
1110
while (true) {
1211
const file = filenames.find(el => fs.existsSync(path.resolve(dir, el)))
1312

src/utils/read-pkg-up.ts

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ function stripBOM(str: string) {
88
return str.replace(/^\uFEFF/, '')
99
}
1010

11-
// eslint-disable-next-line eslint-plugin/require-meta-docs-description, eslint-plugin/require-meta-type, eslint-plugin/prefer-message-ids, eslint-plugin/prefer-object-rule, eslint-plugin/require-meta-schema
1211
export function readPkgUp(opts?: { cwd?: string }) {
1312
const fp = pkgUp(opts)
1413

test/fixtures/deprecated.js

+5
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,8 @@ export function fine() {
5050
export function _undocumented() {
5151
return 'sneaky!'
5252
}
53+
54+
/** @deprecated */
55+
export function _deprecatedNoDescription() {
56+
return '_deprecatedNoDescription'
57+
}

0 commit comments

Comments
 (0)