@blumintinc/eslint-plugin-blumint 1.1.8 → 1.1.9
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/index.js
CHANGED
|
@@ -46,17 +46,21 @@ exports.classMethodsReadTopToBottom = (0, createRule_1.createRule)({
|
|
|
46
46
|
const newClassBody = sortedOrder
|
|
47
47
|
.map((n) => {
|
|
48
48
|
// Fetch the actual AST node corresponding to the name
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
50
49
|
const memberNode = node.body.find((member) => getMemberName(member) === n);
|
|
50
|
+
if (!memberNode) {
|
|
51
|
+
return '';
|
|
52
|
+
}
|
|
51
53
|
const comments = sourceCode.getCommentsBefore(memberNode) || [];
|
|
52
|
-
|
|
54
|
+
const nodeRange = memberNode.range;
|
|
55
|
+
const newRange = comments.length > 0
|
|
53
56
|
? [
|
|
54
|
-
Math.min(
|
|
55
|
-
Math.max(
|
|
57
|
+
Math.min(nodeRange[0], Math.min(...comments.map((comment) => comment.range[0]))),
|
|
58
|
+
Math.max(nodeRange[1], Math.max(...comments.map((comment) => comment.range[1]))),
|
|
56
59
|
]
|
|
57
|
-
:
|
|
58
|
-
return sourceCode.getText(memberNode);
|
|
60
|
+
: nodeRange;
|
|
61
|
+
return sourceCode.getText({ ...memberNode, range: newRange });
|
|
59
62
|
})
|
|
63
|
+
.filter(Boolean)
|
|
60
64
|
.join('\n');
|
|
61
65
|
return context.report({
|
|
62
66
|
node,
|
|
@@ -34,6 +34,10 @@ function isMutableValue(node) {
|
|
|
34
34
|
if (node.type === 'CallExpression') {
|
|
35
35
|
const callee = node.callee;
|
|
36
36
|
if (callee.type === 'MemberExpression') {
|
|
37
|
+
// Handle both Identifier and non-Identifier property nodes
|
|
38
|
+
if (callee.property.type !== 'Identifier') {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
37
41
|
const methodName = callee.property.name;
|
|
38
42
|
const mutatingMethods = [
|
|
39
43
|
'slice',
|
|
@@ -20,6 +20,8 @@ exports.default = (0, createRule_1.createRule)({
|
|
|
20
20
|
},
|
|
21
21
|
defaultOptions: [],
|
|
22
22
|
create(context) {
|
|
23
|
+
// Check if the file is a TypeScript file
|
|
24
|
+
const isTypeScript = context.getFilename().endsWith('.ts') || context.getFilename().endsWith('.tsx');
|
|
23
25
|
return {
|
|
24
26
|
VariableDeclaration(node) {
|
|
25
27
|
// Only check top-level const declarations
|
|
@@ -30,18 +32,40 @@ exports.default = (0, createRule_1.createRule)({
|
|
|
30
32
|
if (node.parent?.type !== utils_1.AST_NODE_TYPES.Program) {
|
|
31
33
|
return;
|
|
32
34
|
}
|
|
33
|
-
// Skip if any declaration is a function component
|
|
35
|
+
// Skip if any declaration is a function component, arrow function, forwardRef, or memo
|
|
34
36
|
const shouldSkip = node.declarations.some(declaration => {
|
|
35
37
|
if (declaration.id.type !== utils_1.AST_NODE_TYPES.Identifier) {
|
|
36
38
|
return false;
|
|
37
39
|
}
|
|
38
40
|
const name = declaration.id.name;
|
|
39
41
|
const init = declaration.init;
|
|
40
|
-
|
|
42
|
+
// Skip if no initializer
|
|
43
|
+
if (!init) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
41
46
|
// Skip function components (uppercase name + arrow function)
|
|
42
|
-
(/^[A-Z]/.test(name) && init
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
if (/^[A-Z]/.test(name) && init.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
// Skip any arrow function
|
|
51
|
+
if (init.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
// Skip forwardRef and memo calls
|
|
55
|
+
if (init.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
56
|
+
if (init.callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
57
|
+
return ['forwardRef', 'memo'].includes(init.callee.name);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Skip type assertions on forwardRef and memo calls
|
|
61
|
+
if (init.type === utils_1.AST_NODE_TYPES.TSAsExpression) {
|
|
62
|
+
const expression = init.expression;
|
|
63
|
+
if (expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
|
64
|
+
expression.callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
65
|
+
return ['forwardRef', 'memo'].includes(expression.callee.name);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
45
69
|
});
|
|
46
70
|
if (shouldSkip) {
|
|
47
71
|
return;
|
|
@@ -53,10 +77,11 @@ exports.default = (0, createRule_1.createRule)({
|
|
|
53
77
|
}
|
|
54
78
|
const { name } = declaration.id;
|
|
55
79
|
const init = declaration.init;
|
|
56
|
-
// Skip if no initializer or if it's a dynamic value
|
|
80
|
+
// Skip if no initializer or if it's a dynamic value or class instance
|
|
57
81
|
if (!init ||
|
|
58
82
|
init.type === utils_1.AST_NODE_TYPES.CallExpression ||
|
|
59
|
-
init.type === utils_1.AST_NODE_TYPES.BinaryExpression
|
|
83
|
+
init.type === utils_1.AST_NODE_TYPES.BinaryExpression ||
|
|
84
|
+
init.type === utils_1.AST_NODE_TYPES.NewExpression) {
|
|
60
85
|
return;
|
|
61
86
|
}
|
|
62
87
|
// Check for UPPER_SNAKE_CASE
|
|
@@ -73,34 +98,36 @@ exports.default = (0, createRule_1.createRule)({
|
|
|
73
98
|
},
|
|
74
99
|
});
|
|
75
100
|
}
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
node.typeAnnotation?.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
};
|
|
84
|
-
const shouldHaveAsConst = (node) => {
|
|
85
|
-
// Skip if it's already an as const expression
|
|
86
|
-
if (isAsConstExpression(node)) {
|
|
101
|
+
// Only check for as const in TypeScript files
|
|
102
|
+
if (isTypeScript) {
|
|
103
|
+
const isAsConstExpression = (node) => {
|
|
104
|
+
if (node.type === utils_1.AST_NODE_TYPES.TSAsExpression) {
|
|
105
|
+
return (node.typeAnnotation?.type === utils_1.AST_NODE_TYPES.TSTypeReference &&
|
|
106
|
+
node.typeAnnotation?.typeName?.name === 'const');
|
|
107
|
+
}
|
|
87
108
|
return false;
|
|
109
|
+
};
|
|
110
|
+
const shouldHaveAsConst = (node) => {
|
|
111
|
+
// Skip if it's already an as const expression
|
|
112
|
+
if (isAsConstExpression(node)) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
// Check if it's a literal, array, or object that should have as const
|
|
116
|
+
return (node.type === utils_1.AST_NODE_TYPES.Literal ||
|
|
117
|
+
node.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
|
|
118
|
+
node.type === utils_1.AST_NODE_TYPES.ObjectExpression);
|
|
119
|
+
};
|
|
120
|
+
if (shouldHaveAsConst(init)) {
|
|
121
|
+
context.report({
|
|
122
|
+
node: init,
|
|
123
|
+
messageId: 'asConst',
|
|
124
|
+
fix(fixer) {
|
|
125
|
+
const sourceCode = context.getSourceCode();
|
|
126
|
+
const initText = sourceCode.getText(init);
|
|
127
|
+
return fixer.replaceText(init, `${initText} as const`);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
88
130
|
}
|
|
89
|
-
// Check if it's a literal, array, or object that should have as const
|
|
90
|
-
return (node.type === utils_1.AST_NODE_TYPES.Literal ||
|
|
91
|
-
node.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
|
|
92
|
-
node.type === utils_1.AST_NODE_TYPES.ObjectExpression);
|
|
93
|
-
};
|
|
94
|
-
if (shouldHaveAsConst(init)) {
|
|
95
|
-
context.report({
|
|
96
|
-
node: init,
|
|
97
|
-
messageId: 'asConst',
|
|
98
|
-
fix(fixer) {
|
|
99
|
-
const sourceCode = context.getSourceCode();
|
|
100
|
-
const initText = sourceCode.getText(init);
|
|
101
|
-
return fixer.replaceText(init, `${initText} as const`);
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
131
|
}
|
|
105
132
|
});
|
|
106
133
|
},
|