eslint-plugin-absolute 0.2.4 → 0.2.6
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/dist/index.js
CHANGED
|
@@ -219,55 +219,140 @@ var sortKeysFixable = {
|
|
|
219
219
|
const natural = option && typeof option.natural === "boolean" ? option.natural : false;
|
|
220
220
|
const minKeys = option && typeof option.minKeys === "number" ? option.minKeys : 2;
|
|
221
221
|
const variablesBeforeFunctions = option && typeof option.variablesBeforeFunctions === "boolean" ? option.variablesBeforeFunctions : false;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
222
|
+
const compareKeys = (keyLeft, keyRight) => {
|
|
223
|
+
let left = keyLeft;
|
|
224
|
+
let right = keyRight;
|
|
225
|
+
if (!caseSensitive) {
|
|
226
|
+
left = left.toLowerCase();
|
|
227
|
+
right = right.toLowerCase();
|
|
228
|
+
}
|
|
229
|
+
if (natural) {
|
|
230
|
+
return left.localeCompare(right, undefined, {
|
|
231
|
+
numeric: true
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
return left.localeCompare(right);
|
|
235
|
+
};
|
|
236
|
+
const addImportBindings = (statement) => {
|
|
237
|
+
if (statement.specifiers.length === 0) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
for (const specifier of statement.specifiers) {
|
|
241
|
+
topLevelBindings.set(specifier.local.name, {
|
|
242
|
+
kind: "import"
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const addVariableBinding = (declaration) => {
|
|
247
|
+
if (declaration.id.type !== "Identifier" || !declaration.init) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (declaration.init.type === "ArrowFunctionExpression" || declaration.init.type === "FunctionExpression") {
|
|
251
|
+
topLevelBindings.set(declaration.id.name, {
|
|
252
|
+
kind: "function",
|
|
253
|
+
node: declaration.init
|
|
254
|
+
});
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
topLevelBindings.set(declaration.id.name, {
|
|
258
|
+
kind: "value",
|
|
259
|
+
node: declaration.init
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
const addTopLevelBindings = (statement) => {
|
|
263
|
+
if (statement.type === "ImportDeclaration") {
|
|
264
|
+
addImportBindings(statement);
|
|
265
|
+
return;
|
|
230
266
|
}
|
|
231
267
|
if (statement.type === "FunctionDeclaration" && statement.id) {
|
|
232
268
|
topLevelBindings.set(statement.id.name, {
|
|
233
269
|
kind: "function",
|
|
234
270
|
node: statement
|
|
235
271
|
});
|
|
236
|
-
|
|
272
|
+
return;
|
|
237
273
|
}
|
|
238
274
|
if (statement.type !== "VariableDeclaration" || statement.kind !== "const") {
|
|
239
|
-
|
|
275
|
+
return;
|
|
240
276
|
}
|
|
241
277
|
for (const declaration of statement.declarations) {
|
|
242
|
-
|
|
243
|
-
|
|
278
|
+
addVariableBinding(declaration);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
for (const statement of sourceCode.ast.body) {
|
|
282
|
+
addTopLevelBindings(statement);
|
|
283
|
+
}
|
|
284
|
+
const addBoundIdentifiers = (node, stableLocals) => {
|
|
285
|
+
if (!node) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
switch (node.type) {
|
|
289
|
+
case "Identifier":
|
|
290
|
+
stableLocals.add(node.name);
|
|
291
|
+
return;
|
|
292
|
+
case "AssignmentPattern":
|
|
293
|
+
addBoundIdentifiers(node.left, stableLocals);
|
|
294
|
+
return;
|
|
295
|
+
case "RestElement":
|
|
296
|
+
addBoundIdentifiers(node.argument, stableLocals);
|
|
297
|
+
return;
|
|
298
|
+
case "ArrayPattern":
|
|
299
|
+
for (const element of node.elements.filter(Boolean)) {
|
|
300
|
+
addBoundIdentifiers(element, stableLocals);
|
|
301
|
+
}
|
|
302
|
+
break;
|
|
303
|
+
case "ObjectPattern":
|
|
304
|
+
for (const property of node.properties) {
|
|
305
|
+
const bindingNode = property.type === "RestElement" ? property.argument : property.value;
|
|
306
|
+
addBoundIdentifiers(bindingNode, stableLocals);
|
|
307
|
+
}
|
|
308
|
+
break;
|
|
309
|
+
default:
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
const addFunctionParamBindings = (functionNode, stableLocals) => {
|
|
314
|
+
for (const parameter of functionNode.params) {
|
|
315
|
+
addBoundIdentifiers(parameter, stableLocals);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
const addAncestorConstBindings = (ancestor, node, stableLocals) => {
|
|
319
|
+
const addDeclarationBindings = (statement) => {
|
|
320
|
+
if (statement.type !== "VariableDeclaration" || statement.kind !== "const") {
|
|
321
|
+
return;
|
|
244
322
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
kind: "function",
|
|
248
|
-
node: declaration.init
|
|
249
|
-
});
|
|
250
|
-
continue;
|
|
323
|
+
for (const declaration of statement.declarations) {
|
|
324
|
+
addBoundIdentifiers(declaration.id, stableLocals);
|
|
251
325
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
326
|
+
};
|
|
327
|
+
for (const statement of ancestor.body) {
|
|
328
|
+
if (statement.range[0] >= node.range[0]) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
addDeclarationBindings(statement);
|
|
256
332
|
}
|
|
257
|
-
}
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (!caseSensitive) {
|
|
262
|
-
left = left.toLowerCase();
|
|
263
|
-
right = right.toLowerCase();
|
|
333
|
+
};
|
|
334
|
+
const addAncestorBindingsForNode = (ancestor, node, stableLocals) => {
|
|
335
|
+
if (ancestor.type !== "Program" && ancestor.type !== "BlockStatement") {
|
|
336
|
+
return;
|
|
264
337
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
338
|
+
addAncestorConstBindings(ancestor, node, stableLocals);
|
|
339
|
+
};
|
|
340
|
+
const addFunctionBindingsForAncestor = (ancestor, stableLocals) => {
|
|
341
|
+
if (ancestor.type !== "FunctionDeclaration" && ancestor.type !== "FunctionExpression" && ancestor.type !== "ArrowFunctionExpression") {
|
|
342
|
+
return;
|
|
269
343
|
}
|
|
270
|
-
|
|
344
|
+
addFunctionParamBindings(ancestor, stableLocals);
|
|
345
|
+
};
|
|
346
|
+
const getStableLocalsForNode = (node) => {
|
|
347
|
+
const stableLocals = new Set;
|
|
348
|
+
const ancestors = sourceCode.getAncestors(node);
|
|
349
|
+
for (const ancestor of ancestors) {
|
|
350
|
+
addFunctionBindingsForAncestor(ancestor, stableLocals);
|
|
351
|
+
}
|
|
352
|
+
for (const ancestor of ancestors) {
|
|
353
|
+
addAncestorBindingsForNode(ancestor, node, stableLocals);
|
|
354
|
+
}
|
|
355
|
+
return stableLocals;
|
|
271
356
|
};
|
|
272
357
|
const getStaticMemberName = (memberExpression) => {
|
|
273
358
|
if (!memberExpression.computed && memberExpression.property.type === "Identifier") {
|
|
@@ -294,6 +379,39 @@ var sortKeysFixable = {
|
|
|
294
379
|
}
|
|
295
380
|
return false;
|
|
296
381
|
};
|
|
382
|
+
const isPureConstStatement = (statement, stableLocals, checkExpression) => {
|
|
383
|
+
if (statement.kind !== "const") {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
for (const declaration of statement.declarations) {
|
|
387
|
+
if (declaration.id.type !== "Identifier" || !declaration.init) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
if (!checkExpression(declaration.init)) {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
stableLocals.add(declaration.id.name);
|
|
394
|
+
}
|
|
395
|
+
return true;
|
|
396
|
+
};
|
|
397
|
+
const isPureFunctionStatement = (statement, stableLocals, checkExpression) => {
|
|
398
|
+
if (statement.type === "ReturnStatement") {
|
|
399
|
+
return !statement.argument || checkExpression(statement.argument);
|
|
400
|
+
}
|
|
401
|
+
if (statement.type === "VariableDeclaration") {
|
|
402
|
+
return isPureConstStatement(statement, stableLocals, checkExpression);
|
|
403
|
+
}
|
|
404
|
+
return false;
|
|
405
|
+
};
|
|
406
|
+
const isPureFunctionBody = (body, stableLocals, checkExpression) => {
|
|
407
|
+
for (const statement of body.body) {
|
|
408
|
+
const statementIsPure = isPureFunctionStatement(statement, stableLocals, checkExpression);
|
|
409
|
+
if (!statementIsPure) {
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return true;
|
|
414
|
+
};
|
|
297
415
|
const isPureTopLevelFunction = (functionNode) => {
|
|
298
416
|
const cached = pureFunctionCache.get(functionNode);
|
|
299
417
|
if (cached !== undefined) {
|
|
@@ -304,44 +422,23 @@ var sortKeysFixable = {
|
|
|
304
422
|
}
|
|
305
423
|
pureFunctionInProgress.add(functionNode);
|
|
306
424
|
const stableLocals = new Set;
|
|
307
|
-
|
|
308
|
-
if (parameter.type === "Identifier") {
|
|
309
|
-
stableLocals.add(parameter.name);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
let isPure = true;
|
|
425
|
+
addFunctionParamBindings(functionNode, stableLocals);
|
|
313
426
|
const checkExpression = (expression) => isPureRuntimeExpression(expression, stableLocals);
|
|
314
|
-
|
|
315
|
-
for (const statement of functionNode.body.body) {
|
|
316
|
-
if (statement.type === "ReturnStatement") {
|
|
317
|
-
if (statement.argument && !checkExpression(statement.argument)) {
|
|
318
|
-
isPure = false;
|
|
319
|
-
}
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
if (statement.type === "VariableDeclaration" && statement.kind === "const") {
|
|
323
|
-
for (const declaration of statement.declarations) {
|
|
324
|
-
if (declaration.id.type !== "Identifier" || !declaration.init || !checkExpression(declaration.init)) {
|
|
325
|
-
isPure = false;
|
|
326
|
-
break;
|
|
327
|
-
}
|
|
328
|
-
stableLocals.add(declaration.id.name);
|
|
329
|
-
}
|
|
330
|
-
if (!isPure) {
|
|
331
|
-
break;
|
|
332
|
-
}
|
|
333
|
-
continue;
|
|
334
|
-
}
|
|
335
|
-
isPure = false;
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
} else {
|
|
339
|
-
isPure = checkExpression(functionNode.body);
|
|
340
|
-
}
|
|
427
|
+
const isPure = functionNode.body.type === "BlockStatement" ? isPureFunctionBody(functionNode.body, stableLocals, checkExpression) : checkExpression(functionNode.body);
|
|
341
428
|
pureFunctionInProgress.delete(functionNode);
|
|
342
429
|
pureFunctionCache.set(functionNode, isPure);
|
|
343
430
|
return isPure;
|
|
344
431
|
};
|
|
432
|
+
const isPureIdentifierCall = (callExpression) => {
|
|
433
|
+
if (callExpression.callee.type !== "Identifier") {
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
if (PURE_GLOBAL_FUNCTIONS.has(callExpression.callee.name)) {
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
const binding = topLevelBindings.get(callExpression.callee.name);
|
|
440
|
+
return binding?.kind === "function" ? isPureTopLevelFunction(binding.node) : false;
|
|
441
|
+
};
|
|
345
442
|
const isPureRuntimeExpression = (node, stableLocals) => {
|
|
346
443
|
if (!node || node.type === "PrivateIdentifier") {
|
|
347
444
|
return false;
|
|
@@ -405,11 +502,7 @@ var sortKeysFixable = {
|
|
|
405
502
|
return false;
|
|
406
503
|
}
|
|
407
504
|
if (node.callee.type === "Identifier") {
|
|
408
|
-
|
|
409
|
-
return true;
|
|
410
|
-
}
|
|
411
|
-
const binding = topLevelBindings.get(node.callee.name);
|
|
412
|
-
return binding?.kind === "function" && isPureTopLevelFunction(binding.node);
|
|
505
|
+
return isPureIdentifierCall(node);
|
|
413
506
|
}
|
|
414
507
|
if (node.callee.type !== "MemberExpression") {
|
|
415
508
|
return false;
|
|
@@ -424,8 +517,7 @@ var sortKeysFixable = {
|
|
|
424
517
|
return false;
|
|
425
518
|
}
|
|
426
519
|
};
|
|
427
|
-
const
|
|
428
|
-
const isSafeJSXAttributeValue = (value) => {
|
|
520
|
+
const isSafeJSXAttributeValue = (value, scopeNode) => {
|
|
429
521
|
if (value === null) {
|
|
430
522
|
return true;
|
|
431
523
|
}
|
|
@@ -438,7 +530,7 @@ var sortKeysFixable = {
|
|
|
438
530
|
if (value.expression.type === "JSXEmptyExpression") {
|
|
439
531
|
return false;
|
|
440
532
|
}
|
|
441
|
-
return
|
|
533
|
+
return isPureRuntimeExpression(value.expression, getStableLocalsForNode(scopeNode));
|
|
442
534
|
};
|
|
443
535
|
const isFunctionProperty = (prop) => {
|
|
444
536
|
const { value } = prop;
|
|
@@ -586,7 +678,7 @@ ${indent}`;
|
|
|
586
678
|
if (hasDuplicateNames(keys.map((key) => key.keyName))) {
|
|
587
679
|
autoFixable = false;
|
|
588
680
|
}
|
|
589
|
-
if (autoFixable && keys.some((key) => key.node.type === "Property" && !
|
|
681
|
+
if (autoFixable && keys.some((key) => key.node.type === "Property" && !isPureRuntimeExpression(key.node.value, getStableLocalsForNode(key.node)))) {
|
|
590
682
|
autoFixable = false;
|
|
591
683
|
}
|
|
592
684
|
let fixProvided = false;
|
|
@@ -685,7 +777,7 @@ ${indent}`;
|
|
|
685
777
|
});
|
|
686
778
|
return;
|
|
687
779
|
}
|
|
688
|
-
if (attrs.some((attr) => attr.type === "JSXAttribute" && !isSafeJSXAttributeValue(attr.value))) {
|
|
780
|
+
if (attrs.some((attr) => attr.type === "JSXAttribute" && !isSafeJSXAttributeValue(attr.value, attr))) {
|
|
689
781
|
context.report({
|
|
690
782
|
messageId: "unsorted",
|
|
691
783
|
node: attrs[0].type === "JSXAttribute" ? attrs[0].name : attrs[0]
|
package/package.json
CHANGED