eslint-plugin-unicorn 61.0.0 → 61.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/package.json
CHANGED
|
@@ -35,9 +35,8 @@ const getProblem = (valueNode, fix, reportNode) => {
|
|
|
35
35
|
messageId: MESSAGE_ID_ERROR,
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
const shouldUseSuggestion = valueNode.type
|
|
39
|
-
|
|
40
|
-
: !(isExpressionStatement(valueNode) || isExpressionStatement(valueNode.parent));
|
|
38
|
+
const shouldUseSuggestion = valueNode.type !== 'IfStatement'
|
|
39
|
+
&& !(isExpressionStatement(valueNode) || isExpressionStatement(valueNode.parent));
|
|
41
40
|
|
|
42
41
|
if (shouldUseSuggestion) {
|
|
43
42
|
problem.suggest = [
|
|
@@ -78,6 +77,40 @@ const getConditionText = (node, sourceCode, isNegative) => {
|
|
|
78
77
|
return text;
|
|
79
78
|
};
|
|
80
79
|
|
|
80
|
+
const isClassListMethodCall = (node, methods) =>
|
|
81
|
+
isMethodCall(node, {
|
|
82
|
+
methods,
|
|
83
|
+
argumentsLength: 1,
|
|
84
|
+
optionalCall: false,
|
|
85
|
+
optionalMember: false,
|
|
86
|
+
})
|
|
87
|
+
&& isClassList(node.callee.object);
|
|
88
|
+
|
|
89
|
+
const isSameElementAndClassName = (callExpressionA, callExpressionB) =>
|
|
90
|
+
isSameReference(callExpressionA.callee.object, callExpressionB.callee.object)
|
|
91
|
+
&& isSameReference(callExpressionA.arguments[0], callExpressionB.arguments[0]);
|
|
92
|
+
|
|
93
|
+
const getClassListContainsCall = (conditionNode, isNegative, addOrRemoveCall) => {
|
|
94
|
+
if (!isNegative) {
|
|
95
|
+
if (conditionNode.type === 'UnaryExpression' && conditionNode.operator === '!' && conditionNode.prefix) {
|
|
96
|
+
return getClassListContainsCall(conditionNode.argument, !isNegative, addOrRemoveCall);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (conditionNode.type === 'ChainExpression') {
|
|
103
|
+
conditionNode = conditionNode.expression;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (
|
|
107
|
+
isClassListMethodCall(conditionNode, ['contains'])
|
|
108
|
+
&& isSameElementAndClassName(conditionNode, addOrRemoveCall)
|
|
109
|
+
) {
|
|
110
|
+
return conditionNode;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
81
114
|
/** @param {import('eslint').Rule.RuleContext} context */
|
|
82
115
|
const create = context => {
|
|
83
116
|
const {sourceCode} = context;
|
|
@@ -121,37 +154,30 @@ const create = context => {
|
|
|
121
154
|
|
|
122
155
|
// `element.classList.add('className');`
|
|
123
156
|
// `element.classList.remove('className');`
|
|
124
|
-
if (!clauses.every(node =>
|
|
125
|
-
isMethodCall(node, {
|
|
126
|
-
methods: ['add', 'remove'],
|
|
127
|
-
argumentsLength: 1,
|
|
128
|
-
optionalCall: false,
|
|
129
|
-
optionalMember: false,
|
|
130
|
-
})
|
|
131
|
-
&& isClassList(node.callee.object),
|
|
132
|
-
)) {
|
|
157
|
+
if (!clauses.every(node => isClassListMethodCall(node, ['add', 'remove']))) {
|
|
133
158
|
return;
|
|
134
159
|
}
|
|
135
160
|
|
|
136
161
|
const [consequent, alternate] = clauses;
|
|
137
162
|
if (
|
|
138
163
|
(consequent.callee.property.name === alternate.callee.property.name)
|
|
139
|
-
|| !
|
|
140
|
-
|| !isSameReference(consequent.arguments[0], alternate.arguments[0])
|
|
164
|
+
|| !isSameElementAndClassName(consequent, alternate)
|
|
141
165
|
) {
|
|
142
166
|
return;
|
|
143
167
|
}
|
|
144
168
|
|
|
145
169
|
/** @param {import('eslint').Rule.RuleFixer} fixer */
|
|
146
170
|
function * fix(fixer) {
|
|
147
|
-
const isOptional = consequent.callee.object.optional || alternate.callee.object.optional;
|
|
148
171
|
const elementText = getParenthesizedText(consequent.callee.object.object, sourceCode);
|
|
149
172
|
const classNameText = getParenthesizedText(consequent.arguments[0], sourceCode);
|
|
150
173
|
const isExpression = node.type === 'ConditionalExpression';
|
|
151
174
|
const isNegative = consequent.callee.property.name === 'remove';
|
|
152
|
-
const
|
|
175
|
+
const conditionNode = node.test;
|
|
176
|
+
const classListContainsCall = getClassListContainsCall(conditionNode, isNegative, consequent);
|
|
177
|
+
const conditionText = classListContainsCall ? '' : getConditionText(conditionNode, sourceCode, isNegative);
|
|
178
|
+
const isOptional = consequent.callee.object.optional || alternate.callee.object.optional || classListContainsCall?.callee.object.optional;
|
|
153
179
|
|
|
154
|
-
let text = `${elementText}${isOptional ? '?' : ''}.classList.toggle(${classNameText}
|
|
180
|
+
let text = `${elementText}${isOptional ? '?' : ''}.classList.toggle(${classNameText}${conditionText ? `, ${conditionText}` : ''})`;
|
|
155
181
|
|
|
156
182
|
if (!isExpression) {
|
|
157
183
|
text = `${text};`;
|
|
@@ -195,9 +221,14 @@ const create = context => {
|
|
|
195
221
|
/** @param {import('eslint').Rule.RuleFixer} fixer */
|
|
196
222
|
function * fix(fixer) {
|
|
197
223
|
const isNegative = conditionalExpression.consequent.value === 'remove';
|
|
198
|
-
const
|
|
224
|
+
const conditionNode = conditionalExpression.test;
|
|
225
|
+
const classListContainsCall = getClassListContainsCall(conditionNode, isNegative, callExpression);
|
|
226
|
+
const conditionText = classListContainsCall ? '' : getConditionText(conditionNode, sourceCode, isNegative);
|
|
227
|
+
|
|
228
|
+
if (conditionText) {
|
|
229
|
+
yield fixer.insertTextAfter(callExpression.arguments[0], `, ${conditionText}`);
|
|
230
|
+
}
|
|
199
231
|
|
|
200
|
-
yield fixer.insertTextAfter(callExpression.arguments[0], `, ${conditionText}`);
|
|
201
232
|
yield replaceMemberExpressionProperty(fixer, classListMethod, sourceCode, '.toggle');
|
|
202
233
|
}
|
|
203
234
|
|
|
@@ -85,8 +85,11 @@ export default function simpleArraySearchRule({method, replacement}) {
|
|
|
85
85
|
|
|
86
86
|
const callbackScope = scopeManager.acquire(callback);
|
|
87
87
|
if (
|
|
88
|
+
// Can't use scopeManager in vue template
|
|
89
|
+
// https://github.com/vuejs/vue-eslint-parser/issues/263
|
|
90
|
+
!callbackScope
|
|
88
91
|
// `parameter` is used somewhere else
|
|
89
|
-
findVariable(callbackScope, parameter).references.some(({identifier}) => identifier !== parameterInBinaryExpression)
|
|
92
|
+
|| findVariable(callbackScope, parameter).references.some(({identifier}) => identifier !== parameterInBinaryExpression)
|
|
90
93
|
|| isFunctionSelfUsedInside(callback, callbackScope)
|
|
91
94
|
) {
|
|
92
95
|
return;
|
package/rules/throw-new-error.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {isMemberExpression} from './ast/index.js';
|
|
1
2
|
import {switchCallExpressionToNewExpression} from './fix/index.js';
|
|
2
3
|
|
|
3
4
|
const messageId = 'throw-new-error';
|
|
@@ -23,6 +24,17 @@ const create = context => ({
|
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/issues/2654 (Effect library)
|
|
28
|
+
if (
|
|
29
|
+
isMemberExpression(callee, {
|
|
30
|
+
object: 'Data',
|
|
31
|
+
property: 'TaggedError',
|
|
32
|
+
computed: false,
|
|
33
|
+
})
|
|
34
|
+
) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
26
38
|
return {
|
|
27
39
|
node,
|
|
28
40
|
messageId,
|