eslint-plugin-absolute 0.3.0 → 0.5.0

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.
Files changed (2) hide show
  1. package/dist/index.js +223 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -194,7 +194,9 @@ var PURE_GLOBAL_IDENTIFIERS = new Set([
194
194
  "Boolean",
195
195
  "Date",
196
196
  "Function",
197
+ "JSON",
197
198
  "Map",
199
+ "Math",
198
200
  "Number",
199
201
  "Object",
200
202
  "Promise",
@@ -203,16 +205,131 @@ var PURE_GLOBAL_IDENTIFIERS = new Set([
203
205
  "String",
204
206
  "Symbol",
205
207
  "URL",
208
+ "globalThis",
206
209
  "undefined"
207
210
  ]);
208
- var PURE_GLOBAL_FUNCTIONS = new Set(["Boolean", "Number", "String"]);
211
+ var PURE_GLOBAL_FUNCTIONS = new Set([
212
+ "Boolean",
213
+ "Number",
214
+ "String",
215
+ "decodeURI",
216
+ "decodeURIComponent",
217
+ "encodeURI",
218
+ "encodeURIComponent",
219
+ "isFinite",
220
+ "isNaN",
221
+ "parseFloat",
222
+ "parseInt"
223
+ ]);
209
224
  var PURE_MEMBER_METHODS = new Set([
225
+ "toString",
226
+ "valueOf",
227
+ "at",
228
+ "charAt",
229
+ "charCodeAt",
230
+ "codePointAt",
231
+ "endsWith",
232
+ "includes",
233
+ "indexOf",
234
+ "lastIndexOf",
235
+ "match",
236
+ "matchAll",
237
+ "normalize",
238
+ "padEnd",
239
+ "padStart",
240
+ "repeat",
241
+ "replace",
242
+ "replaceAll",
243
+ "search",
244
+ "slice",
245
+ "split",
246
+ "startsWith",
247
+ "substr",
248
+ "substring",
249
+ "toLocaleLowerCase",
250
+ "toLocaleUpperCase",
251
+ "toLowerCase",
252
+ "toUpperCase",
253
+ "trim",
254
+ "trimEnd",
255
+ "trimStart",
256
+ "toExponential",
257
+ "toFixed",
258
+ "toPrecision",
259
+ "isInteger",
260
+ "isSafeInteger",
261
+ "getDate",
210
262
  "getDay",
263
+ "getFullYear",
211
264
  "getHours",
212
265
  "getMilliseconds",
213
266
  "getMinutes",
267
+ "getMonth",
214
268
  "getSeconds",
215
- "padStart"
269
+ "getTime",
270
+ "getTimezoneOffset",
271
+ "getUTCDate",
272
+ "getUTCDay",
273
+ "getUTCFullYear",
274
+ "getUTCHours",
275
+ "getUTCMilliseconds",
276
+ "getUTCMinutes",
277
+ "getUTCMonth",
278
+ "getUTCSeconds",
279
+ "toDateString",
280
+ "toISOString",
281
+ "toJSON",
282
+ "toLocaleDateString",
283
+ "toLocaleString",
284
+ "toLocaleTimeString",
285
+ "toTimeString",
286
+ "toUTCString",
287
+ "abs",
288
+ "acos",
289
+ "acosh",
290
+ "asin",
291
+ "asinh",
292
+ "atan",
293
+ "atan2",
294
+ "atanh",
295
+ "cbrt",
296
+ "ceil",
297
+ "clz32",
298
+ "cos",
299
+ "cosh",
300
+ "exp",
301
+ "expm1",
302
+ "floor",
303
+ "fround",
304
+ "hypot",
305
+ "log",
306
+ "log10",
307
+ "log1p",
308
+ "log2",
309
+ "max",
310
+ "min",
311
+ "pow",
312
+ "round",
313
+ "sign",
314
+ "sin",
315
+ "sinh",
316
+ "sqrt",
317
+ "tan",
318
+ "tanh",
319
+ "trunc",
320
+ "entries",
321
+ "fromEntries",
322
+ "getOwnPropertyNames",
323
+ "getOwnPropertySymbols",
324
+ "getPrototypeOf",
325
+ "hasOwn",
326
+ "isArray",
327
+ "keys",
328
+ "values",
329
+ "concat",
330
+ "join",
331
+ "parse",
332
+ "stringify"
216
333
  ]);
217
334
  var hasDuplicateNames = (names) => {
218
335
  const seen = new Set;
@@ -225,6 +342,37 @@ var hasDuplicateNames = (names) => {
225
342
  }
226
343
  return false;
227
344
  };
345
+ var hasDuplicatePropertyNames = (properties) => {
346
+ const kindsByName = new Map;
347
+ for (const property of properties) {
348
+ if (property.type !== "Property") {
349
+ continue;
350
+ }
351
+ let keyName = null;
352
+ if (property.key.type === "Identifier") {
353
+ keyName = property.key.name;
354
+ } else if (property.key.type === "Literal") {
355
+ const { value } = property.key;
356
+ keyName = typeof value === "string" ? value : String(value);
357
+ }
358
+ if (keyName === null) {
359
+ continue;
360
+ }
361
+ const kinds = kindsByName.get(keyName) ?? [];
362
+ kinds.push(property.kind);
363
+ kindsByName.set(keyName, kinds);
364
+ }
365
+ for (const kinds of kindsByName.values()) {
366
+ if (kinds.length === 1) {
367
+ continue;
368
+ }
369
+ if (kinds.length === 2 && kinds.includes("get") && kinds.includes("set")) {
370
+ continue;
371
+ }
372
+ return true;
373
+ }
374
+ return false;
375
+ };
228
376
  var sortKeysFixable = {
229
377
  create(context) {
230
378
  const { sourceCode } = context;
@@ -342,7 +490,7 @@ var sortKeysFixable = {
342
490
  };
343
491
  const addAncestorConstBindings = (ancestor, node, stableLocals) => {
344
492
  const addDeclarationBindings = (statement) => {
345
- if (statement.type !== "VariableDeclaration" || statement.kind !== "const") {
493
+ if (statement.type !== "VariableDeclaration") {
346
494
  return;
347
495
  }
348
496
  for (const declaration of statement.declarations) {
@@ -377,6 +525,7 @@ var sortKeysFixable = {
377
525
  for (const ancestor of ancestors) {
378
526
  addAncestorBindingsForNode(ancestor, node, stableLocals);
379
527
  }
528
+ stableLocals.add("this");
380
529
  return stableLocals;
381
530
  };
382
531
  const getStaticMemberName = (memberExpression) => {
@@ -796,10 +945,66 @@ var sortKeysFixable = {
796
945
  }
797
946
  return isPureImportedCallExpression(callExpression);
798
947
  };
948
+ const getCallReturnTypeSymbol = (node) => {
949
+ if (!tsChecker || !esTreeNodeToTSNodeMap)
950
+ return;
951
+ const tsNode = esTreeNodeToTSNodeMap.get(node);
952
+ if (!tsNode)
953
+ return;
954
+ const type = tsChecker.getTypeAtLocation(tsNode);
955
+ return type.symbol ?? type.aliasSymbol;
956
+ };
957
+ const callReturnsNominalInstance = (node) => {
958
+ const symbol = getCallReturnTypeSymbol(node);
959
+ if (!symbol)
960
+ return false;
961
+ const declarations = symbol.declarations;
962
+ if (!declarations)
963
+ return false;
964
+ return declarations.some((declaration) => ts.isClassDeclaration(declaration) || ts.isClassExpression(declaration) || ts.isInterfaceDeclaration(declaration));
965
+ };
966
+ const isEncapsulatedFreshExpression = (node, stableLocals) => {
967
+ if (!node)
968
+ return false;
969
+ if (node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSInstantiationExpression") {
970
+ return isEncapsulatedFreshExpression(node.expression, stableLocals);
971
+ }
972
+ if (node.type === "ObjectExpression" || node.type === "ArrayExpression") {
973
+ return isPureRuntimeExpression(node, stableLocals);
974
+ }
975
+ if (node.type === "NewExpression") {
976
+ return node.arguments.every((argument) => {
977
+ if (argument.type === "SpreadElement") {
978
+ return isPureRuntimeExpression(argument.argument, stableLocals);
979
+ }
980
+ return isPureRuntimeExpression(argument, stableLocals);
981
+ });
982
+ }
983
+ if (node.type === "CallExpression") {
984
+ const argsArePure = node.arguments.every((argument) => {
985
+ if (argument.type === "SpreadElement") {
986
+ return isPureRuntimeExpression(argument.argument, stableLocals);
987
+ }
988
+ return isPureRuntimeExpression(argument, stableLocals);
989
+ });
990
+ if (!argsArePure)
991
+ return false;
992
+ if (node.callee.type === "MemberExpression") {
993
+ return isEncapsulatedFreshExpression(node.callee.object, stableLocals);
994
+ }
995
+ if (node.callee.type === "Identifier") {
996
+ return callReturnsNominalInstance(node);
997
+ }
998
+ }
999
+ return false;
1000
+ };
799
1001
  const isPureRuntimeExpression = (node, stableLocals) => {
800
1002
  if (!node || node.type === "PrivateIdentifier") {
801
1003
  return false;
802
1004
  }
1005
+ if (node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSInstantiationExpression") {
1006
+ return isPureRuntimeExpression(node.expression, stableLocals);
1007
+ }
803
1008
  switch (node.type) {
804
1009
  case "Identifier":
805
1010
  return isStableIdentifier(node.name, stableLocals);
@@ -823,9 +1028,12 @@ var sortKeysFixable = {
823
1028
  return isPureRuntimeExpression(node.test, stableLocals) && isPureRuntimeExpression(node.consequent, stableLocals) && isPureRuntimeExpression(node.alternate, stableLocals);
824
1029
  case "ArrayExpression":
825
1030
  return node.elements.every((element) => {
826
- if (!element || element.type === "SpreadElement") {
1031
+ if (!element) {
827
1032
  return false;
828
1033
  }
1034
+ if (element.type === "SpreadElement") {
1035
+ return isPureRuntimeExpression(element.argument, stableLocals);
1036
+ }
829
1037
  return isPureRuntimeExpression(element, stableLocals);
830
1038
  });
831
1039
  case "ObjectExpression":
@@ -865,7 +1073,10 @@ var sortKeysFixable = {
865
1073
  return true;
866
1074
  }
867
1075
  if (node.callee.type === "Identifier") {
868
- return isPureIdentifierCall(node);
1076
+ if (isPureIdentifierCall(node)) {
1077
+ return true;
1078
+ }
1079
+ return callReturnsNominalInstance(node);
869
1080
  }
870
1081
  if (node.callee.type !== "MemberExpression") {
871
1082
  return false;
@@ -874,6 +1085,12 @@ var sortKeysFixable = {
874
1085
  if (memberName && PURE_MEMBER_METHODS.has(memberName)) {
875
1086
  return isPureRuntimeExpression(node.callee.object, stableLocals);
876
1087
  }
1088
+ if (isEncapsulatedFreshExpression(node.callee.object, stableLocals)) {
1089
+ return true;
1090
+ }
1091
+ if (isPureRuntimeExpression(node.callee.object, stableLocals) && callReturnsNominalInstance(node)) {
1092
+ return true;
1093
+ }
877
1094
  return isPureImportedCallExpression(node);
878
1095
  }
879
1096
  default:
@@ -1038,7 +1255,7 @@ ${indent}`;
1038
1255
  node: prop
1039
1256
  };
1040
1257
  });
1041
- if (hasDuplicateNames(keys.map((key) => key.keyName))) {
1258
+ if (hasDuplicatePropertyNames(node.properties)) {
1042
1259
  autoFixable = false;
1043
1260
  }
1044
1261
  if (autoFixable) {
package/package.json CHANGED
@@ -40,5 +40,5 @@
40
40
  "typecheck": "bun run tsc --noEmit"
41
41
  },
42
42
  "type": "module",
43
- "version": "0.3.0"
43
+ "version": "0.5.0"
44
44
  }