@blumintinc/eslint-plugin-blumint 0.1.23 → 1.0.2
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/CHANGELOG.md +63 -0
- package/README.md +277 -55
- package/assets/logo.svg +26 -0
- package/jest.config.js +13 -0
- package/package.json +74 -25
- package/plugin/README.md +80 -0
- package/{docs → plugin/docs}/rules/class-methods-read-top-to-bottom.md +3 -1
- package/{docs → plugin/docs}/rules/dynamic-https-errors.md +1 -1
- package/{docs → plugin/docs}/rules/require-memo.md +9 -2
- package/plugin/package-lock.json +7662 -0
- package/plugin/package.json +45 -0
- package/tsconfig.json +79 -0
- package/lib/index.js +0 -69
- package/lib/rules/array-methods-this-context.js +0 -64
- package/lib/rules/class-methods-read-top-to-bottom.js +0 -72
- package/lib/rules/dynamic-https-errors.js +0 -57
- package/lib/rules/export-if-in-doubt.js +0 -69
- package/lib/rules/extract-global-constants.js +0 -63
- package/lib/rules/generic-starts-with-t.js +0 -35
- package/lib/rules/no-async-array-filter.js +0 -40
- package/lib/rules/no-async-foreach.js +0 -37
- package/lib/rules/no-conditional-literals-in-jsx.js +0 -61
- package/lib/rules/no-filter-without-return.js +0 -41
- package/lib/rules/no-misused-switch-case.js +0 -35
- package/lib/rules/no-unpinned-dependencies.js +0 -65
- package/lib/rules/no-useless-fragment.js +0 -46
- package/lib/rules/prefer-fragment-shorthand.js +0 -40
- package/lib/rules/prefer-type-over-interface.js +0 -45
- package/lib/rules/require-memo.js +0 -134
- package/lib/utils/ASTHelpers.js +0 -336
- package/lib/utils/ClassGraphBuilder.js +0 -80
- package/lib/utils/ClassGraphSorter.js +0 -99
- package/lib/utils/createRule.js +0 -6
- package/lib/utils/graph/ClassGraphBuilder.js +0 -80
- package/lib/utils/graph/ClassGraphSorter.js +0 -10
- package/lib/utils/graph/ClassGraphSorterReadability.js +0 -94
- package/lib/utils/graph.js +0 -109
- package/lib/utils/ruleTester.js +0 -23
- package/lib/utils/testClass.js +0 -45
- /package/{docs → plugin/docs}/rules/array-methods-this-context.md +0 -0
- /package/{docs → plugin/docs}/rules/export-if-in-doubt.md +0 -0
- /package/{docs → plugin/docs}/rules/extract-global-constants.md +0 -0
- /package/{docs → plugin/docs}/rules/generic-starts-with-t.md +0 -0
- /package/{docs → plugin/docs}/rules/no-async-array-filter.md +0 -0
- /package/{docs → plugin/docs}/rules/no-async-foreach.md +0 -0
- /package/{docs → plugin/docs}/rules/no-conditional-literals-in-jsx.md +0 -0
- /package/{docs → plugin/docs}/rules/no-filter-without-return.md +0 -0
- /package/{docs → plugin/docs}/rules/no-misused-switch-case.md +0 -0
- /package/{docs → plugin/docs}/rules/no-unpinned-dependencies.md +0 -0
- /package/{docs → plugin/docs}/rules/no-useless-fragment.md +0 -0
- /package/{docs → plugin/docs}/rules/prefer-fragment-shorthand.md +0 -0
- /package/{docs → plugin/docs}/rules/prefer-type-over-interface.md +0 -0
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ClassGraphSorterReadability = void 0;
|
|
4
|
-
const ClassGraphSorter_1 = require("./ClassGraphSorter");
|
|
5
|
-
class ClassGraphSorterReadability extends ClassGraphSorter_1.ClassGraphSorter {
|
|
6
|
-
constructor(graph) {
|
|
7
|
-
super(graph);
|
|
8
|
-
this.graph = graph;
|
|
9
|
-
}
|
|
10
|
-
get nodeNamesSorted() {
|
|
11
|
-
return this.nodesSorted.map((node) => node.name);
|
|
12
|
-
}
|
|
13
|
-
get nodesSorted() {
|
|
14
|
-
return this.sortNodes();
|
|
15
|
-
}
|
|
16
|
-
sortNodes() {
|
|
17
|
-
const { methods, properties, classConstructor } = this.groupNodesByType();
|
|
18
|
-
const [propertiesSorted, methodsSorted] = [properties, methods].map((nodeGroup) => nodeGroup.sort(ClassGraphSorterReadability.sortMembersForReadability));
|
|
19
|
-
const searchNodeCandidates = [classConstructor, ...methodsSorted].filter((node) => !!node);
|
|
20
|
-
const searchNodeCandidatesValidated = searchNodeCandidates.filter((method, _index, arr) => ClassGraphSorterReadability.SEARCH_NODE_PRIORITY_FUNCTIONS.some((fn) => !!fn(method, arr)));
|
|
21
|
-
const searchNodesSorted = searchNodeCandidatesValidated.sort((a, b) => {
|
|
22
|
-
const getPriority = (method) => {
|
|
23
|
-
const priority = ClassGraphSorterReadability.SEARCH_NODE_PRIORITY_FUNCTIONS.findIndex((fn) => !!fn(method, methodsSorted));
|
|
24
|
-
return priority === -1
|
|
25
|
-
? ClassGraphSorterReadability.SEARCH_NODE_PRIORITY_FUNCTIONS.length
|
|
26
|
-
: priority;
|
|
27
|
-
};
|
|
28
|
-
return getPriority(a) - getPriority(b);
|
|
29
|
-
});
|
|
30
|
-
const dfsSortedNodes = this.dependencyDfs(searchNodesSorted);
|
|
31
|
-
return [...propertiesSorted, ...dfsSortedNodes];
|
|
32
|
-
}
|
|
33
|
-
groupNodesByType() {
|
|
34
|
-
const nodes = Object.values(this.graph);
|
|
35
|
-
return nodes.reduce((acc, node) => {
|
|
36
|
-
switch (node.type) {
|
|
37
|
-
case 'property':
|
|
38
|
-
acc.properties.push(node);
|
|
39
|
-
break;
|
|
40
|
-
case 'constructor':
|
|
41
|
-
acc.classConstructor = node;
|
|
42
|
-
break;
|
|
43
|
-
case 'method':
|
|
44
|
-
acc.methods.push(node);
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
return acc;
|
|
48
|
-
}, {
|
|
49
|
-
properties: [],
|
|
50
|
-
methods: [],
|
|
51
|
-
classConstructor: null,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
static sortMembersForReadability(a, b) {
|
|
55
|
-
// NOTE: the ordering from Object.entries is safe here since it is readonly
|
|
56
|
-
for (const [key, priorities] of Object.entries(ClassGraphSorterReadability.MODIFIER_PRIORITY_MAP)) {
|
|
57
|
-
const indexA = priorities.indexOf(a[key]);
|
|
58
|
-
const indexB = priorities.indexOf(b[key]);
|
|
59
|
-
if (indexA !== indexB) {
|
|
60
|
-
return indexA - indexB;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return 0;
|
|
64
|
-
}
|
|
65
|
-
dependencyDfs(searchNodes) {
|
|
66
|
-
const visited = new Set();
|
|
67
|
-
const dfsSortedNodes = [];
|
|
68
|
-
const dfs = (node) => {
|
|
69
|
-
if (visited.has(node.name) || !node) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
visited.add(node.name);
|
|
73
|
-
dfsSortedNodes.push(node);
|
|
74
|
-
for (const dep of node.dependencies) {
|
|
75
|
-
dfs(this.graph[String(dep)]);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
searchNodes.forEach((node) => dfs(node));
|
|
79
|
-
return dfsSortedNodes;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
exports.ClassGraphSorterReadability = ClassGraphSorterReadability;
|
|
83
|
-
ClassGraphSorterReadability.MODIFIER_PRIORITY_MAP = {
|
|
84
|
-
isStatic: [true, false],
|
|
85
|
-
accessibility: ['public', undefined, 'private'],
|
|
86
|
-
};
|
|
87
|
-
ClassGraphSorterReadability.SEARCH_NODE_PRIORITY_FUNCTIONS = [
|
|
88
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
89
|
-
(method, _methods) => method.type === 'constructor',
|
|
90
|
-
(method, _methods) => !_methods.some((node) => node.dependencies.includes(method.name)),
|
|
91
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
92
|
-
(method, _methods) => method.dependencies.length === 0,
|
|
93
|
-
];
|
|
94
|
-
//# sourceMappingURL=ClassGraphSorterReadability.js.map
|
package/lib/utils/graph.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.classNodesDfs = exports.ClassGraphSorter = void 0;
|
|
4
|
-
class ClassGraphSorter {
|
|
5
|
-
constructor(graph, sortFunction) {
|
|
6
|
-
this.graph = graph;
|
|
7
|
-
this.sortFunction = sortFunction;
|
|
8
|
-
}
|
|
9
|
-
sort() {
|
|
10
|
-
const nodesGrouped = this.sortFunction(Object.values(this.graph));
|
|
11
|
-
// Additional logic for DFS and sorting will be implemented here
|
|
12
|
-
// Placeholder for the sorted result
|
|
13
|
-
const sortedResult = [];
|
|
14
|
-
// Logic to populate sortedResult
|
|
15
|
-
return sortedResult;
|
|
16
|
-
}
|
|
17
|
-
defaultEnhancedSort(nodes) {
|
|
18
|
-
// Implementation of the default enhanced sort logic
|
|
19
|
-
// This will include sorting by type, static status, and accessibility
|
|
20
|
-
// Placeholder for return value
|
|
21
|
-
return { properties: [], notProperties: [] };
|
|
22
|
-
}
|
|
23
|
-
// Additional private helper methods will be implemented here
|
|
24
|
-
// Placeholder for depth-first search (DFS) logic
|
|
25
|
-
dfs(node, visited, sortedNodes) {
|
|
26
|
-
// Implementation of the DFS logic
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
exports.ClassGraphSorter = ClassGraphSorter;
|
|
30
|
-
function classNodesDfs(graph) {
|
|
31
|
-
const { properties, notProperties } = sortClassMembersForReadability(Object.values(graph));
|
|
32
|
-
//now we have nodes in properties -> constructor -> methods order
|
|
33
|
-
//we need to sort constructor & methods such that
|
|
34
|
-
//if a node has dependencies, then the dependencies are moved after that node in a dfs manner
|
|
35
|
-
const visited = new Set();
|
|
36
|
-
const dfsSortedNodes = [];
|
|
37
|
-
const dfs = (node) => {
|
|
38
|
-
if (visited.has(node.name)) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
visited.add(node.name);
|
|
42
|
-
dfsSortedNodes.push(node);
|
|
43
|
-
for (const dep of node.dependencies) {
|
|
44
|
-
dfs(graph[dep]);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
const searchNodes = notProperties
|
|
48
|
-
.filter((method) => method.type === 'constructor' ||
|
|
49
|
-
!notProperties.some((node) => node.dependencies.includes(method.name)) ||
|
|
50
|
-
method.dependencies.length === 0)
|
|
51
|
-
.sort((a, b) => {
|
|
52
|
-
const getPriority = (method) => {
|
|
53
|
-
if (method.type === 'constructor')
|
|
54
|
-
return 1;
|
|
55
|
-
if (!notProperties.some((node) => node.dependencies.includes(method.name)))
|
|
56
|
-
return 2;
|
|
57
|
-
if (method.dependencies.length === 0)
|
|
58
|
-
return 3;
|
|
59
|
-
return 4; // In case none of the conditions match
|
|
60
|
-
};
|
|
61
|
-
return getPriority(a) - getPriority(b);
|
|
62
|
-
});
|
|
63
|
-
for (const searchNode of searchNodes) {
|
|
64
|
-
dfs(searchNode);
|
|
65
|
-
}
|
|
66
|
-
return [...properties, ...dfsSortedNodes].map((node) => node.name);
|
|
67
|
-
}
|
|
68
|
-
exports.classNodesDfs = classNodesDfs;
|
|
69
|
-
function sortClassMembersForReadability(nodes) {
|
|
70
|
-
// 1. Group nodes by type
|
|
71
|
-
const properties = [];
|
|
72
|
-
const methods = [];
|
|
73
|
-
let constructor = null;
|
|
74
|
-
for (const node of nodes) {
|
|
75
|
-
switch (node.type) {
|
|
76
|
-
case 'property':
|
|
77
|
-
properties.push(node);
|
|
78
|
-
break;
|
|
79
|
-
case 'constructor':
|
|
80
|
-
constructor = node;
|
|
81
|
-
break;
|
|
82
|
-
case 'method':
|
|
83
|
-
methods.push(node);
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// 2. Fine-tune ordering within each group
|
|
88
|
-
// For properties and methods
|
|
89
|
-
const comparator = (a, b) => {
|
|
90
|
-
// Static methods/properties come first
|
|
91
|
-
if (a.isStatic && !b.isStatic)
|
|
92
|
-
return -1;
|
|
93
|
-
if (!a.isStatic && b.isStatic)
|
|
94
|
-
return 1;
|
|
95
|
-
const accessibilityA = a.accessibility ?? 'public';
|
|
96
|
-
const accessibilityB = b.accessibility ?? 'public';
|
|
97
|
-
if (accessibilityA === 'public' && accessibilityB === 'private')
|
|
98
|
-
return -1;
|
|
99
|
-
if (accessibilityA === 'private' && accessibilityB === 'public')
|
|
100
|
-
return 1;
|
|
101
|
-
// Maintain original order otherwise
|
|
102
|
-
return 0;
|
|
103
|
-
};
|
|
104
|
-
properties.sort(comparator);
|
|
105
|
-
methods.sort(comparator);
|
|
106
|
-
// Return the nodes in the desired order
|
|
107
|
-
return { properties, notProperties: [constructor, ...methods] };
|
|
108
|
-
}
|
|
109
|
-
//# sourceMappingURL=graph.js.map
|
package/lib/utils/ruleTester.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ruleTesterJson = exports.ruleTesterJsx = exports.ruleTesterTs = void 0;
|
|
4
|
-
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
-
const eslint_1 = require("eslint");
|
|
6
|
-
exports.ruleTesterTs = new utils_1.ESLintUtils.RuleTester({
|
|
7
|
-
parser: '@typescript-eslint/parser',
|
|
8
|
-
});
|
|
9
|
-
exports.ruleTesterJsx = new utils_1.ESLintUtils.RuleTester({
|
|
10
|
-
parser: '@typescript-eslint/parser',
|
|
11
|
-
parserOptions: {
|
|
12
|
-
ecmaFeatures: {
|
|
13
|
-
jsx: true,
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
exports.ruleTesterJson = new eslint_1.RuleTester({
|
|
18
|
-
parser: require.resolve('jsonc-eslint-parser'),
|
|
19
|
-
parserOptions: {
|
|
20
|
-
ecmaVersion: 2020,
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
//# sourceMappingURL=ruleTester.js.map
|
package/lib/utils/testClass.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ASTHelpers = void 0;
|
|
4
|
-
class ASTHelpers {
|
|
5
|
-
constructor() {
|
|
6
|
-
ASTHelpers.returnsJSX;
|
|
7
|
-
}
|
|
8
|
-
static returnsJSX(node) {
|
|
9
|
-
if (node.type === 'JSXElement' || node.type === 'JSXFragment') {
|
|
10
|
-
return true;
|
|
11
|
-
}
|
|
12
|
-
this.bar();
|
|
13
|
-
if (node.type === 'BlockStatement') {
|
|
14
|
-
for (const statement of node.body) {
|
|
15
|
-
if (statement.type === 'ReturnStatement' &&
|
|
16
|
-
(statement.argument?.type === 'JSXElement' ||
|
|
17
|
-
statement.argument?.type === 'JSXFragment')) {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
// Handle conditional returns
|
|
21
|
-
if (statement.type === 'ReturnStatement' &&
|
|
22
|
-
statement.argument?.type === 'ConditionalExpression') {
|
|
23
|
-
const conditionalExpr = statement.argument;
|
|
24
|
-
if (ASTHelpers.returnsJSX(conditionalExpr.consequent) ||
|
|
25
|
-
ASTHelpers.returnsJSX(conditionalExpr.alternate)) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
if (node.type === 'ConditionalExpression') {
|
|
32
|
-
return (ASTHelpers.returnsJSX(node.consequent) ||
|
|
33
|
-
ASTHelpers.returnsJSX(node.alternate));
|
|
34
|
-
}
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
bar() {
|
|
38
|
-
this.foo();
|
|
39
|
-
}
|
|
40
|
-
foo() {
|
|
41
|
-
return ASTHelpers.returnsJSX(node);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
exports.ASTHelpers = ASTHelpers;
|
|
45
|
-
//# sourceMappingURL=testClass.js.map
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|