@mrpalmer/eslint-plugin 1.0.0 → 1.0.1
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/lib/rules/shorten-paths.js +1 -1
- package/lib/rules/sort-imports.d.ts +1 -1
- package/lib/rules/sort-imports.js +23 -27
- package/lib/rules/sort-named.d.ts +1 -1
- package/lib/rules/sort-named.js +21 -22
- package/lib/utils/ast.d.ts +1 -1
- package/lib/utils/ast.js +3 -3
- package/package.json +8 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { createRule } from '../utils/create-rule.js';
|
|
3
|
-
import { loadConfig } from '../utils/ts-config.js';
|
|
4
3
|
import { getImportPathOptions } from '../utils/import-path-options.js';
|
|
5
4
|
import { getShortestPath } from '../utils/shortest-path.js';
|
|
5
|
+
import { loadConfig } from '../utils/ts-config.js';
|
|
6
6
|
export default createRule({
|
|
7
7
|
meta: {
|
|
8
8
|
type: 'suggestion',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TSESLint } from '@typescript-eslint/utils';
|
|
2
2
|
import { type MinimatchOptions } from 'minimatch';
|
|
3
3
|
import type { Arrayable } from '../types.js';
|
|
4
4
|
import { type ImportType as ImportType_ } from '../utils/import-type.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/types';
|
|
2
2
|
import { minimatch } from 'minimatch';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { findOutOfOrder, groupBy, reverse } from '../utils/array.js';
|
|
4
|
+
import { findEndOfLineWithComments, findRootNode, findStartOfLineWithComments, } from '../utils/ast.js';
|
|
5
5
|
import { createRule } from '../utils/create-rule.js';
|
|
6
|
+
import { importType, } from '../utils/import-type.js';
|
|
6
7
|
import { getSettings } from '../utils/settings.js';
|
|
7
8
|
import { loadConfig } from '../utils/ts-config.js';
|
|
8
|
-
import { importType, } from '../utils/import-type.js';
|
|
9
9
|
const categories = {
|
|
10
10
|
import: 'import',
|
|
11
11
|
exports: 'exports',
|
|
@@ -21,34 +21,34 @@ const defaultGroups = [
|
|
|
21
21
|
// REPORTING AND FIXING
|
|
22
22
|
function isRequireExpression(expr) {
|
|
23
23
|
return (expr != null &&
|
|
24
|
-
expr.type ===
|
|
24
|
+
expr.type === AST_NODE_TYPES.CallExpression &&
|
|
25
25
|
// eslint-disable-next-line eslint-plugin/no-property-in-node
|
|
26
26
|
'name' in expr.callee &&
|
|
27
27
|
expr.callee.name === 'require' &&
|
|
28
28
|
expr.arguments.length === 1 &&
|
|
29
|
-
expr.arguments[0].type ===
|
|
29
|
+
expr.arguments[0].type === AST_NODE_TYPES.Literal);
|
|
30
30
|
}
|
|
31
31
|
function isSupportedRequireModule(node) {
|
|
32
|
-
if (node.type !==
|
|
32
|
+
if (node.type !== AST_NODE_TYPES.VariableDeclaration) {
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
if (node.declarations.length !== 1) {
|
|
36
36
|
return false;
|
|
37
37
|
}
|
|
38
38
|
const decl = node.declarations[0];
|
|
39
|
-
const isPlainRequire = (decl.id.type ===
|
|
40
|
-
decl.id.type ===
|
|
39
|
+
const isPlainRequire = (decl.id.type === AST_NODE_TYPES.Identifier ||
|
|
40
|
+
decl.id.type === AST_NODE_TYPES.ObjectPattern) &&
|
|
41
41
|
isRequireExpression(decl.init);
|
|
42
|
-
const isRequireWithMemberExpression = (decl.id.type ===
|
|
43
|
-
decl.id.type ===
|
|
42
|
+
const isRequireWithMemberExpression = (decl.id.type === AST_NODE_TYPES.Identifier ||
|
|
43
|
+
decl.id.type === AST_NODE_TYPES.ObjectPattern) &&
|
|
44
44
|
decl.init != null &&
|
|
45
|
-
decl.init.type ===
|
|
46
|
-
decl.init.callee.type ===
|
|
45
|
+
decl.init.type === AST_NODE_TYPES.CallExpression &&
|
|
46
|
+
decl.init.callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
47
47
|
isRequireExpression(decl.init.callee.object);
|
|
48
48
|
return isPlainRequire || isRequireWithMemberExpression;
|
|
49
49
|
}
|
|
50
50
|
function isPlainImportModule(node) {
|
|
51
|
-
return node.type ===
|
|
51
|
+
return node.type === AST_NODE_TYPES.ImportDeclaration;
|
|
52
52
|
}
|
|
53
53
|
function canCrossNodeWhileReorder(node) {
|
|
54
54
|
return isSupportedRequireModule(node) || isPlainImportModule(node);
|
|
@@ -276,8 +276,7 @@ function registerNode(context, settings, importEntry, ranks, imported) {
|
|
|
276
276
|
if (rank !== -1) {
|
|
277
277
|
let importNode = importEntry.node;
|
|
278
278
|
if (importEntry.type === 'require' &&
|
|
279
|
-
importNode.parent?.parent?.type ===
|
|
280
|
-
TSESTree.AST_NODE_TYPES.VariableDeclaration) {
|
|
279
|
+
importNode.parent?.parent?.type === AST_NODE_TYPES.VariableDeclaration) {
|
|
281
280
|
importNode = importNode.parent.parent;
|
|
282
281
|
}
|
|
283
282
|
imported.push({
|
|
@@ -292,7 +291,7 @@ function registerNode(context, settings, importEntry, ranks, imported) {
|
|
|
292
291
|
}
|
|
293
292
|
}
|
|
294
293
|
function isSideEffectImport(node, sourceCode) {
|
|
295
|
-
if (node.type !==
|
|
294
|
+
if (node.type !== AST_NODE_TYPES.ImportDeclaration) {
|
|
296
295
|
return false;
|
|
297
296
|
}
|
|
298
297
|
return (node.specifiers.length === 0 &&
|
|
@@ -300,22 +299,19 @@ function isSideEffectImport(node, sourceCode) {
|
|
|
300
299
|
!isPunctuator(sourceCode.getFirstToken(node, { skip: 1 }), '{'));
|
|
301
300
|
}
|
|
302
301
|
function isPunctuator(token, value) {
|
|
303
|
-
return (token &&
|
|
304
|
-
token.type === TSESTree.AST_TOKEN_TYPES.Punctuator &&
|
|
305
|
-
token.value === value);
|
|
302
|
+
return (token && token.type === AST_TOKEN_TYPES.Punctuator && token.value === value);
|
|
306
303
|
}
|
|
307
304
|
function getRequireBlock(node) {
|
|
308
305
|
let n = node;
|
|
309
306
|
// Handle cases like `const baz = require('foo').bar.baz`
|
|
310
307
|
// and `const foo = require('foo')()`
|
|
311
|
-
while ((n.parent?.type ===
|
|
308
|
+
while ((n.parent?.type === AST_NODE_TYPES.MemberExpression &&
|
|
312
309
|
n.parent.object === n) ||
|
|
313
|
-
(n.parent?.type ===
|
|
314
|
-
n.parent.callee === n)) {
|
|
310
|
+
(n.parent?.type === AST_NODE_TYPES.CallExpression && n.parent.callee === n)) {
|
|
315
311
|
n = n.parent;
|
|
316
312
|
}
|
|
317
|
-
if (n.parent?.type ===
|
|
318
|
-
n.parent.parent.parent.type ===
|
|
313
|
+
if (n.parent?.type === AST_NODE_TYPES.VariableDeclarator &&
|
|
314
|
+
n.parent.parent.parent.type === AST_NODE_TYPES.Program) {
|
|
319
315
|
return n.parent.parent.parent;
|
|
320
316
|
}
|
|
321
317
|
return undefined;
|
|
@@ -628,9 +624,9 @@ function getErrorMessage(error) {
|
|
|
628
624
|
return undefined;
|
|
629
625
|
}
|
|
630
626
|
function isStaticRequire(node) {
|
|
631
|
-
return (node.callee.type ===
|
|
627
|
+
return (node.callee.type === AST_NODE_TYPES.Identifier &&
|
|
632
628
|
node.callee.name === 'require' &&
|
|
633
629
|
node.arguments.length === 1 &&
|
|
634
|
-
node.arguments[0].type ===
|
|
630
|
+
node.arguments[0].type === AST_NODE_TYPES.Literal &&
|
|
635
631
|
typeof node.arguments[0].value === 'string');
|
|
636
632
|
}
|
package/lib/rules/sort-named.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { groupBy, reverse
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
2
|
+
import { findOutOfOrder, groupBy, reverse } from '../utils/array.js';
|
|
3
3
|
import { createRule } from '../utils/create-rule.js';
|
|
4
4
|
//region rule
|
|
5
5
|
// REPORTING AND FIXING
|
|
@@ -21,24 +21,23 @@ function findSpecifierEnd(sourceCode, node) {
|
|
|
21
21
|
}
|
|
22
22
|
function isRequireExpression(expr) {
|
|
23
23
|
return (expr != null &&
|
|
24
|
-
expr.type ===
|
|
25
|
-
expr.callee.type ===
|
|
24
|
+
expr.type === AST_NODE_TYPES.CallExpression &&
|
|
25
|
+
expr.callee.type === AST_NODE_TYPES.Identifier &&
|
|
26
26
|
expr.callee.name === 'require' &&
|
|
27
27
|
expr.arguments.length === 1 &&
|
|
28
|
-
expr.arguments[0].type ===
|
|
28
|
+
expr.arguments[0].type === AST_NODE_TYPES.Literal);
|
|
29
29
|
}
|
|
30
30
|
function isCJSExports(context, node) {
|
|
31
|
-
if (node.type ===
|
|
32
|
-
node.object.type ===
|
|
33
|
-
node.property.type ===
|
|
31
|
+
if (node.type === AST_NODE_TYPES.MemberExpression &&
|
|
32
|
+
node.object.type === AST_NODE_TYPES.Identifier &&
|
|
33
|
+
node.property.type === AST_NODE_TYPES.Identifier &&
|
|
34
34
|
node.object.name === 'module' &&
|
|
35
35
|
node.property.name === 'exports') {
|
|
36
36
|
return !context.sourceCode
|
|
37
37
|
.getScope(node)
|
|
38
38
|
.variables.some((variable) => variable.name === 'module');
|
|
39
39
|
}
|
|
40
|
-
if (node.type ===
|
|
41
|
-
node.name === 'exports') {
|
|
40
|
+
if (node.type === AST_NODE_TYPES.Identifier && node.name === 'exports') {
|
|
42
41
|
return !context.sourceCode
|
|
43
42
|
.getScope(node)
|
|
44
43
|
.variables.some((variable) => variable.name === 'exports');
|
|
@@ -46,14 +45,14 @@ function isCJSExports(context, node) {
|
|
|
46
45
|
return false;
|
|
47
46
|
}
|
|
48
47
|
function getNamedCJSExports(context, node) {
|
|
49
|
-
if (node.type !==
|
|
48
|
+
if (node.type !== AST_NODE_TYPES.MemberExpression) {
|
|
50
49
|
return undefined;
|
|
51
50
|
}
|
|
52
51
|
const result = [];
|
|
53
52
|
let root = node;
|
|
54
53
|
let parent;
|
|
55
|
-
while (root.type ===
|
|
56
|
-
if (root.property.type !==
|
|
54
|
+
while (root.type === AST_NODE_TYPES.MemberExpression) {
|
|
55
|
+
if (root.property.type !== AST_NODE_TYPES.Identifier) {
|
|
57
56
|
return undefined;
|
|
58
57
|
}
|
|
59
58
|
result.unshift(root.property.name);
|
|
@@ -259,13 +258,13 @@ function makeOutOfOrderReport(context, imported) {
|
|
|
259
258
|
}
|
|
260
259
|
function isSimpleObjectPropertyList(properties) {
|
|
261
260
|
return properties.every((p) => {
|
|
262
|
-
if (p.type !==
|
|
261
|
+
if (p.type !== AST_NODE_TYPES.Property) {
|
|
263
262
|
return false;
|
|
264
263
|
}
|
|
265
|
-
if (p.key.type !==
|
|
264
|
+
if (p.key.type !== AST_NODE_TYPES.Identifier) {
|
|
266
265
|
return false;
|
|
267
266
|
}
|
|
268
|
-
return p.value.type ===
|
|
267
|
+
return p.value.type === AST_NODE_TYPES.Identifier;
|
|
269
268
|
});
|
|
270
269
|
}
|
|
271
270
|
export default createRule({
|
|
@@ -337,7 +336,7 @@ export default createRule({
|
|
|
337
336
|
return;
|
|
338
337
|
}
|
|
339
338
|
makeNamedOrderReport(context, node.specifiers
|
|
340
|
-
.filter((specifier) => specifier.type ===
|
|
339
|
+
.filter((specifier) => specifier.type === AST_NODE_TYPES.ImportSpecifier)
|
|
341
340
|
.map((specifier) => ({
|
|
342
341
|
node: specifier,
|
|
343
342
|
value: getValue(specifier.imported),
|
|
@@ -349,7 +348,7 @@ export default createRule({
|
|
|
349
348
|
})));
|
|
350
349
|
},
|
|
351
350
|
VariableDeclarator(node) {
|
|
352
|
-
if (node.id.type ===
|
|
351
|
+
if (node.id.type === AST_NODE_TYPES.ObjectPattern &&
|
|
353
352
|
isRequireExpression(node.init)) {
|
|
354
353
|
const { properties } = node.id;
|
|
355
354
|
if (!isSimpleObjectPropertyList(properties)) {
|
|
@@ -381,9 +380,9 @@ export default createRule({
|
|
|
381
380
|
})));
|
|
382
381
|
},
|
|
383
382
|
AssignmentExpression(node) {
|
|
384
|
-
if (node.parent.type ===
|
|
383
|
+
if (node.parent.type === AST_NODE_TYPES.ExpressionStatement) {
|
|
385
384
|
if (isCJSExports(context, node.left)) {
|
|
386
|
-
if (node.right.type ===
|
|
385
|
+
if (node.right.type === AST_NODE_TYPES.ObjectExpression) {
|
|
387
386
|
const { properties } = node.right;
|
|
388
387
|
if (!isSimpleObjectPropertyList(properties)) {
|
|
389
388
|
return;
|
|
@@ -425,9 +424,9 @@ export default createRule({
|
|
|
425
424
|
//region utils
|
|
426
425
|
function getValue(node) {
|
|
427
426
|
switch (node.type) {
|
|
428
|
-
case
|
|
427
|
+
case AST_NODE_TYPES.Identifier:
|
|
429
428
|
return node.name;
|
|
430
|
-
case
|
|
429
|
+
case AST_NODE_TYPES.Literal:
|
|
431
430
|
return node.value;
|
|
432
431
|
default:
|
|
433
432
|
throw new Error(`Unsupported node type: ${node.type}`);
|
package/lib/utils/ast.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
2
|
export declare function findRootNode(node: TSESTree.Node): TSESTree.Node;
|
|
3
3
|
export declare function findEndOfLineWithComments(sourceCode: TSESLint.SourceCode, node: TSESTree.Node): number;
|
|
4
4
|
export declare function findStartOfLineWithComments(sourceCode: TSESLint.SourceCode, node: TSESTree.Node): number;
|
package/lib/utils/ast.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AST_TOKEN_TYPES } from '@typescript-eslint/types';
|
|
2
2
|
export function findRootNode(node) {
|
|
3
3
|
let parent = node;
|
|
4
4
|
while (parent.parent != null &&
|
|
@@ -83,8 +83,8 @@ export function findEndOfLineWithComments(sourceCode, node) {
|
|
|
83
83
|
return result;
|
|
84
84
|
}
|
|
85
85
|
function commentOnSameLineAs(node) {
|
|
86
|
-
return (token) => (token.type ===
|
|
87
|
-
token.type ===
|
|
86
|
+
return (token) => (token.type === AST_TOKEN_TYPES.Block ||
|
|
87
|
+
token.type === AST_TOKEN_TYPES.Line) &&
|
|
88
88
|
token.loc.start.line === token.loc.end.line &&
|
|
89
89
|
token.loc.end.line === node.loc.end.line;
|
|
90
90
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrpalmer/eslint-plugin",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Custom ESLint rules for Mike Palmer's projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -16,13 +16,19 @@
|
|
|
16
16
|
"lib"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@typescript-eslint/
|
|
19
|
+
"@typescript-eslint/types": "^8.36.0",
|
|
20
20
|
"get-tsconfig": "^4.10.0",
|
|
21
21
|
"minimatch": "^10.0.1"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
+
"@typescript-eslint/utils": "^8.0.0",
|
|
24
25
|
"eslint": "^9.0.0"
|
|
25
26
|
},
|
|
27
|
+
"peerDependenciesMeta": {
|
|
28
|
+
"@typescript-eslint/utils": {
|
|
29
|
+
"optional": true
|
|
30
|
+
}
|
|
31
|
+
},
|
|
26
32
|
"engines": {
|
|
27
33
|
"node": ">=20",
|
|
28
34
|
"npm": ">=8",
|