@taiga-ui/eslint-plugin-experience-next 0.474.0 → 0.476.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 (52) hide show
  1. package/README.md +106 -0
  2. package/index.d.ts +12 -0
  3. package/index.esm.js +698 -538
  4. package/package.json +1 -1
  5. package/rules/no-commonjs-import-patterns.d.ts +6 -0
  6. package/rules/no-fully-untracked-effect.d.ts +1 -2
  7. package/rules/no-import-assertions.d.ts +5 -0
  8. package/rules/no-infinite-loop.d.ts +6 -0
  9. package/rules/no-signal-reads-after-await-in-reactive-context.d.ts +1 -2
  10. package/rules/no-untracked-outside-reactive-context.d.ts +1 -2
  11. package/rules/no-useless-untracked.d.ts +1 -2
  12. package/rules/prefer-namespace-keyword.d.ts +5 -0
  13. package/rules/prefer-untracked-incidental-signal-reads.d.ts +1 -27
  14. package/rules/prefer-untracked-signal-getter.d.ts +1 -2
  15. package/rules/utils/{angular-signals.d.ts → angular/angular-signals.d.ts} +9 -5
  16. package/rules/utils/angular/pipes.d.ts +2 -0
  17. package/rules/utils/angular/providers.d.ts +3 -0
  18. package/rules/utils/ast/ancestors.d.ts +12 -0
  19. package/rules/utils/{ast-walk.d.ts → ast/ast-walk.d.ts} +1 -0
  20. package/rules/utils/ast/call-expressions.d.ts +2 -0
  21. package/rules/utils/ast/mutation-targets.d.ts +4 -0
  22. package/rules/utils/ast/parenthesized.d.ts +3 -0
  23. package/rules/utils/ast/property-names.d.ts +5 -0
  24. package/rules/utils/ast/returned-expression.d.ts +2 -0
  25. package/rules/utils/ast/string-literals.d.ts +10 -0
  26. package/rules/utils/text/dedent.d.ts +5 -0
  27. package/rules/utils/typescript/decorators.d.ts +2 -0
  28. package/rules/utils/typescript/function-usage.d.ts +5 -0
  29. package/rules/utils/typescript/node-map.d.ts +6 -0
  30. package/rules/utils/typescript/symbols.d.ts +4 -0
  31. package/rules/utils/typescript/type-aware-context.d.ts +14 -0
  32. /package/rules/utils/{angular-imports.d.ts → angular/angular-imports.d.ts} +0 -0
  33. /package/rules/utils/{get-decorator-metadata.d.ts → angular/get-decorator-metadata.d.ts} +0 -0
  34. /package/rules/utils/{get-imports-array.d.ts → angular/get-imports-array.d.ts} +0 -0
  35. /package/rules/utils/{import-fix-helpers.d.ts → angular/import-fix-helpers.d.ts} +0 -0
  36. /package/rules/utils/{is-imports-array-property.d.ts → angular/is-imports-array-property.d.ts} +0 -0
  37. /package/rules/utils/{untracked-docs.d.ts → angular/untracked-docs.d.ts} +0 -0
  38. /package/rules/utils/{ast-expressions.d.ts → ast/ast-expressions.d.ts} +0 -0
  39. /package/rules/utils/{get-const-array.d.ts → ast/get-const-array.d.ts} +0 -0
  40. /package/rules/utils/{is-array.d.ts → ast/is-array.d.ts} +0 -0
  41. /package/rules/utils/{is-object.d.ts → ast/is-object.d.ts} +0 -0
  42. /package/rules/utils/{is-spread.d.ts → ast/is-spread.d.ts} +0 -0
  43. /package/rules/utils/{name-of.d.ts → ast/name-of.d.ts} +0 -0
  44. /package/rules/utils/{intersect.d.ts → collections/intersect.d.ts} +0 -0
  45. /package/rules/utils/{same-order.d.ts → collections/same-order.d.ts} +0 -0
  46. /package/rules/utils/{get-imported-name.d.ts → imports/get-imported-name.d.ts} +0 -0
  47. /package/rules/utils/{npmrc-parser.d.ts → parsers/npmrc-parser.d.ts} +0 -0
  48. /package/rules/utils/{get-sorted-names.d.ts → sorting/get-sorted-names.d.ts} +0 -0
  49. /package/rules/utils/{get-field-types.d.ts → typescript/get-field-types.d.ts} +0 -0
  50. /package/rules/utils/{get-type-name.d.ts → typescript/get-type-name.d.ts} +0 -0
  51. /package/rules/utils/{is-class-type.d.ts → typescript/is-class-type.d.ts} +0 -0
  52. /package/rules/utils/{is-external-tuple.d.ts → typescript/is-external-tuple.d.ts} +0 -0
package/index.esm.js CHANGED
@@ -898,6 +898,7 @@ var recommended = defineConfig([
898
898
  ],
899
899
  '@taiga-ui/experience-next/host-attributes-sort': 'error',
900
900
  '@taiga-ui/experience-next/injection-token-description': 'error',
901
+ '@taiga-ui/experience-next/no-commonjs-import-patterns': 'error',
901
902
  '@taiga-ui/experience-next/no-deep-imports': [
902
903
  'error',
903
904
  {
@@ -908,6 +909,8 @@ var recommended = defineConfig([
908
909
  '@taiga-ui/experience-next/no-deep-imports-to-indexed-packages': 'error',
909
910
  '@taiga-ui/experience-next/no-fully-untracked-effect': 'error',
910
911
  '@taiga-ui/experience-next/no-implicit-public': 'error',
912
+ '@taiga-ui/experience-next/no-import-assertions': 'error',
913
+ '@taiga-ui/experience-next/no-infinite-loop': 'error',
911
914
  '@taiga-ui/experience-next/no-redundant-type-annotation': 'error',
912
915
  '@taiga-ui/experience-next/no-side-effects-in-computed': 'error',
913
916
  '@taiga-ui/experience-next/no-signal-reads-after-await-in-reactive-context': 'error',
@@ -916,6 +919,7 @@ var recommended = defineConfig([
916
919
  '@taiga-ui/experience-next/object-single-line': ['error', { printWidth: 90 }],
917
920
  '@taiga-ui/experience-next/prefer-combined-if-control-flow': 'error',
918
921
  '@taiga-ui/experience-next/prefer-multi-arg-push': 'error',
922
+ '@taiga-ui/experience-next/prefer-namespace-keyword': 'error',
919
923
  '@taiga-ui/experience-next/prefer-untracked-incidental-signal-reads': 'error',
920
924
  '@taiga-ui/experience-next/prefer-untracked-signal-getter': 'error',
921
925
  '@taiga-ui/experience-next/short-tui-imports': 'error',
@@ -1299,6 +1303,11 @@ const config$4 = {
1299
1303
  },
1300
1304
  };
1301
1305
 
1306
+ function intersect(a, b) {
1307
+ const origin = new Set(b);
1308
+ return a.some((type) => origin.has(type));
1309
+ }
1310
+
1302
1311
  function getFieldTypes(type, checker) {
1303
1312
  const typeNames = [];
1304
1313
  if (type.isUnionOrIntersection()) {
@@ -1331,16 +1340,24 @@ function getFieldTypes(type, checker) {
1331
1340
  return typeNames;
1332
1341
  }
1333
1342
 
1334
- function intersect(a, b) {
1335
- const origin = new Set(b);
1336
- return a.some((type) => origin.has(type));
1343
+ function getTypeAwareRuleContext(context) {
1344
+ const parserServices = ESLintUtils.getParserServices(context);
1345
+ const { sourceCode } = context;
1346
+ return {
1347
+ checker: parserServices.program.getTypeChecker(),
1348
+ esTreeNodeToTSNodeMap: parserServices.esTreeNodeToTSNodeMap,
1349
+ parserServices,
1350
+ program: sourceCode.ast,
1351
+ sourceCode,
1352
+ tsNodeToESTreeNodeMap: parserServices.tsNodeToESTreeNodeMap,
1353
+ tsProgram: parserServices.program,
1354
+ };
1337
1355
  }
1338
1356
 
1339
- const createRule$i = ESLintUtils.RuleCreator((name) => name);
1340
- var classPropertyNaming = createRule$i({
1357
+ const createRule$m = ESLintUtils.RuleCreator((name) => name);
1358
+ var classPropertyNaming = createRule$m({
1341
1359
  create(context, [configs]) {
1342
- const parserServices = ESLintUtils.getParserServices(context);
1343
- const typeChecker = parserServices.program.getTypeChecker();
1360
+ const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
1344
1361
  const flatConfig = configs.flat();
1345
1362
  return {
1346
1363
  PropertyDefinition(node) {
@@ -1348,7 +1365,7 @@ var classPropertyNaming = createRule$i({
1348
1365
  if (!fieldName) {
1349
1366
  return;
1350
1367
  }
1351
- const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
1368
+ const tsNode = esTreeNodeToTSNodeMap.get(node);
1352
1369
  const nodeType = typeChecker.getTypeAtLocation(tsNode);
1353
1370
  const fieldTypes = getFieldTypes(nodeType, typeChecker);
1354
1371
  const rule = flatConfig.find((rule) => intersect(fieldTypes, rule.withTypesSpecifier) &&
@@ -1404,6 +1421,10 @@ var classPropertyNaming = createRule$i({
1404
1421
  name: 'class-property-naming',
1405
1422
  });
1406
1423
 
1424
+ function sameOrder(a, b) {
1425
+ return a.length === b.length && a.every((value, index) => value === b[index]);
1426
+ }
1427
+
1407
1428
  const config$3 = {
1408
1429
  create(context) {
1409
1430
  const order = context.options[0] || {};
@@ -1422,7 +1443,7 @@ const config$3 = {
1422
1443
  .map((prop) => prop.key?.name)
1423
1444
  .filter(Boolean);
1424
1445
  const correct = getCorrectOrderRelative(orderList, current);
1425
- if (!isCorrectSortedAccording(correct, current)) {
1446
+ if (!sameOrder(correct, current.filter((item) => correct.includes(item)))) {
1426
1447
  context.report({
1427
1448
  fix: (fixer) => {
1428
1449
  const fileContent = context.sourceCode.text;
@@ -1458,10 +1479,6 @@ const config$3 = {
1458
1479
  type: 'problem',
1459
1480
  },
1460
1481
  };
1461
- function isCorrectSortedAccording(correct, current) {
1462
- return (JSON.stringify(correct) ===
1463
- JSON.stringify(current.filter((item) => correct.includes(item))));
1464
- }
1465
1482
  function getCorrectOrderRelative(correct, current) {
1466
1483
  return correct.filter((item) => current.includes(item));
1467
1484
  }
@@ -1506,12 +1523,11 @@ function isExternalPureTuple(typeChecker, type) {
1506
1523
  return typeArgs.every((item) => isClassType(item));
1507
1524
  }
1508
1525
 
1509
- const createRule$h = ESLintUtils.RuleCreator((name) => name);
1526
+ const createRule$l = ESLintUtils.RuleCreator((name) => name);
1510
1527
  const MESSAGE_ID$7 = 'spreadArrays';
1511
- var flatExports = createRule$h({
1528
+ var flatExports = createRule$l({
1512
1529
  create(context) {
1513
- const parserServices = ESLintUtils.getParserServices(context);
1514
- const typeChecker = parserServices.program.getTypeChecker();
1530
+ const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
1515
1531
  const arrays = new Map();
1516
1532
  const purityCache = new WeakMap();
1517
1533
  const isPureArray = (arr) => {
@@ -1595,7 +1611,7 @@ var flatExports = createRule$h({
1595
1611
  isDirty = true;
1596
1612
  continue;
1597
1613
  }
1598
- const tsNode = parserServices.esTreeNodeToTSNodeMap.get(el);
1614
+ const tsNode = esTreeNodeToTSNodeMap.get(el);
1599
1615
  const elType = typeChecker.getTypeAtLocation(tsNode);
1600
1616
  const isClass = isClassType(elType);
1601
1617
  const isArrayLike = typeChecker.isArrayLikeType(elType) ||
@@ -1675,8 +1691,53 @@ function getDecoratorMetadata(decorator, allowedNames) {
1675
1691
  return isObject(arg) ? arg : null;
1676
1692
  }
1677
1693
 
1678
- function sameOrder(a, b) {
1679
- return a.length === b.length && a.every((value, index) => value === b[index]);
1694
+ function isStringLiteral(node) {
1695
+ return node?.type === AST_NODE_TYPES.Literal && typeof node.value === 'string';
1696
+ }
1697
+ function isStaticTemplateLiteral(node) {
1698
+ return (node?.type === AST_NODE_TYPES.TemplateLiteral &&
1699
+ node.expressions.length === 0 &&
1700
+ node.quasis.length === 1);
1701
+ }
1702
+ function getStaticStringValue(node) {
1703
+ if (isStringLiteral(node)) {
1704
+ return node.value;
1705
+ }
1706
+ if (!isStaticTemplateLiteral(node)) {
1707
+ return null;
1708
+ }
1709
+ return node.quasis[0]?.value.cooked ?? node.quasis[0]?.value.raw ?? '';
1710
+ }
1711
+ function isEmptyStaticString(node) {
1712
+ return getStaticStringValue(node) === '';
1713
+ }
1714
+
1715
+ function getStaticPropertyName(key) {
1716
+ if (key.type === AST_NODE_TYPES.Identifier) {
1717
+ return key.name;
1718
+ }
1719
+ if (key.type === AST_NODE_TYPES.Literal &&
1720
+ (typeof key.value === 'string' || typeof key.value === 'number')) {
1721
+ return String(key.value);
1722
+ }
1723
+ return getStaticStringValue(key);
1724
+ }
1725
+ function getObjectPropertyName(node) {
1726
+ if (node.computed) {
1727
+ return null;
1728
+ }
1729
+ return getStaticPropertyName(node.key);
1730
+ }
1731
+ function getMemberExpressionPropertyName(node) {
1732
+ if (!node.computed && node.property.type === AST_NODE_TYPES.Identifier) {
1733
+ return node.property.name;
1734
+ }
1735
+ return node.computed ? getStaticStringValue(node.property) : null;
1736
+ }
1737
+ function getClassMemberName(member) {
1738
+ return member.key.type === AST_NODE_TYPES.PrivateIdentifier
1739
+ ? null
1740
+ : getStaticPropertyName(member.key);
1680
1741
  }
1681
1742
 
1682
1743
  const DEFAULT_GROUP = '$DEFAULT';
@@ -1744,8 +1805,8 @@ const PRESETS = {
1744
1805
  $VUE: ['$CLASS', '$ID', '$VUE_ATTRIBUTE'],
1745
1806
  $VUE_ATTRIBUTE: /^v-/,
1746
1807
  };
1747
- const createRule$g = ESLintUtils.RuleCreator((name) => name);
1748
- const rule$j = createRule$g({
1808
+ const createRule$k = ESLintUtils.RuleCreator((name) => name);
1809
+ const rule$n = createRule$k({
1749
1810
  create(context, [options]) {
1750
1811
  const sourceCode = context.sourceCode;
1751
1812
  const settings = {
@@ -1867,21 +1928,6 @@ function getHostAttributeProperties(hostObject) {
1867
1928
  }
1868
1929
  return properties;
1869
1930
  }
1870
- function getStaticPropertyName(key) {
1871
- if (key.type === AST_NODE_TYPES$1.Identifier) {
1872
- return key.name;
1873
- }
1874
- if (key.type === AST_NODE_TYPES$1.Literal &&
1875
- (typeof key.value === 'string' || typeof key.value === 'number')) {
1876
- return String(key.value);
1877
- }
1878
- if (key.type === AST_NODE_TYPES$1.TemplateLiteral &&
1879
- key.expressions.length === 0 &&
1880
- key.quasis.length === 1) {
1881
- return key.quasis[0]?.value.cooked ?? null;
1882
- }
1883
- return null;
1884
- }
1885
1931
  function organizeProperties(properties, options) {
1886
1932
  const groups = getGroups(options.attributeGroups.length > 0 ? options.attributeGroups : ['$ANGULAR'], options.attributeIgnoreCase);
1887
1933
  const defaultGroup = ensureDefaultGroup(groups);
@@ -2021,7 +2067,7 @@ const config$2 = {
2021
2067
  const MESSAGE_ID$5 = 'invalid-injection-token-description';
2022
2068
  const ERROR_MESSAGE$3 = "InjectionToken's description should contain token's name";
2023
2069
  const NG_DEV_MODE = 'ngDevMode';
2024
- const createRule$f = ESLintUtils.RuleCreator((name) => name);
2070
+ const createRule$j = ESLintUtils.RuleCreator((name) => name);
2025
2071
  function getVariableName(node) {
2026
2072
  if (node.parent.type !== AST_NODE_TYPES$1.VariableDeclarator) {
2027
2073
  return undefined;
@@ -2029,21 +2075,18 @@ function getVariableName(node) {
2029
2075
  const { id } = node.parent;
2030
2076
  return id.type === AST_NODE_TYPES$1.Identifier ? id.name : undefined;
2031
2077
  }
2032
- function isStringLiteral$1(node) {
2033
- return node.type === AST_NODE_TYPES$1.Literal && typeof node.value === 'string';
2034
- }
2035
2078
  function isStringLike(node) {
2036
- return isStringLiteral$1(node) || node.type === AST_NODE_TYPES$1.TemplateLiteral;
2079
+ return isStringLiteral(node) || node.type === AST_NODE_TYPES$1.TemplateLiteral;
2037
2080
  }
2038
2081
  function getStringValue(node) {
2039
- if (isStringLiteral$1(node)) {
2082
+ if (isStringLiteral(node)) {
2040
2083
  return node.value;
2041
2084
  }
2042
2085
  return node.quasis[0]?.value.raw || '';
2043
2086
  }
2044
- function isEmptyString$1(node) {
2045
- return (getStringValue(node) === '' &&
2046
- (!('expressions' in node) || !node.expressions.length));
2087
+ function isEmptyString(node) {
2088
+ return (isEmptyStaticString(node) &&
2089
+ (!('expressions' in node) || node.expressions.length === 0));
2047
2090
  }
2048
2091
  function isNgDevModeConditional(node) {
2049
2092
  return (node.type === AST_NODE_TYPES$1.ConditionalExpression &&
@@ -2051,7 +2094,7 @@ function isNgDevModeConditional(node) {
2051
2094
  node.test.name === NG_DEV_MODE &&
2052
2095
  isStringLike(node.consequent) &&
2053
2096
  isStringLike(node.alternate) &&
2054
- isEmptyString$1(node.alternate));
2097
+ isEmptyString(node.alternate));
2055
2098
  }
2056
2099
  function getDescriptionValue(node) {
2057
2100
  if (isStringLike(node)) {
@@ -2092,7 +2135,7 @@ function getNgDevModeDeclarationFix(program, fixer) {
2092
2135
  }
2093
2136
  return fixer.insertTextBeforeRange([0, 0], 'declare const ngDevMode: boolean;\n');
2094
2137
  }
2095
- const rule$i = createRule$f({
2138
+ const rule$m = createRule$j({
2096
2139
  create(context) {
2097
2140
  const { sourceCode } = context;
2098
2141
  const program = sourceCode.ast;
@@ -2141,6 +2184,88 @@ const rule$i = createRule$f({
2141
2184
  name: 'injection-token-description',
2142
2185
  });
2143
2186
 
2187
+ const createRule$i = ESLintUtils.RuleCreator((name) => name);
2188
+ function getResolvedVariable(sourceCode, node) {
2189
+ const scope = sourceCode.getScope(node);
2190
+ const reference = scope.references.find((item) => item.identifier === node);
2191
+ return reference?.resolved ?? null;
2192
+ }
2193
+ const rule$l = createRule$i({
2194
+ create(context) {
2195
+ const { sourceCode } = context;
2196
+ const namespaceImports = new Map();
2197
+ const markNamespaceImportAsUsedLikeValue = (identifier) => {
2198
+ const usage = namespaceImports.get(identifier.name);
2199
+ if (!usage ||
2200
+ usage.usedLikeValue ||
2201
+ getResolvedVariable(sourceCode, identifier) !== usage.variable) {
2202
+ return;
2203
+ }
2204
+ usage.usedLikeValue = true;
2205
+ };
2206
+ return {
2207
+ 'CallExpression > Identifier.callee'(node) {
2208
+ markNamespaceImportAsUsedLikeValue(node);
2209
+ },
2210
+ ImportDeclaration(node) {
2211
+ const namespaceImport = node.specifiers.find((specifier) => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier);
2212
+ if (!namespaceImport) {
2213
+ return;
2214
+ }
2215
+ const [variable] = sourceCode.getDeclaredVariables(namespaceImport);
2216
+ if (!variable) {
2217
+ return;
2218
+ }
2219
+ namespaceImports.set(namespaceImport.local.name, {
2220
+ node: namespaceImport,
2221
+ usedLikeValue: false,
2222
+ variable,
2223
+ });
2224
+ },
2225
+ 'NewExpression > Identifier.callee'(node) {
2226
+ markNamespaceImportAsUsedLikeValue(node);
2227
+ },
2228
+ 'Program:exit'() {
2229
+ for (const usage of namespaceImports.values()) {
2230
+ if (!usage.usedLikeValue) {
2231
+ continue;
2232
+ }
2233
+ context.report({
2234
+ data: { name: usage.node.local.name },
2235
+ messageId: 'avoidCallableNamespaceImport',
2236
+ node: usage.node,
2237
+ });
2238
+ }
2239
+ },
2240
+ 'TaggedTemplateExpression > Identifier.tag'(node) {
2241
+ markNamespaceImportAsUsedLikeValue(node);
2242
+ },
2243
+ TSImportEqualsDeclaration(node) {
2244
+ if (node.moduleReference.type !== AST_NODE_TYPES.TSExternalModuleReference) {
2245
+ return;
2246
+ }
2247
+ context.report({
2248
+ data: { name: node.id.name },
2249
+ messageId: 'avoidImportEquals',
2250
+ node,
2251
+ });
2252
+ },
2253
+ };
2254
+ },
2255
+ meta: {
2256
+ docs: {
2257
+ description: 'Disallow legacy CommonJS interop import patterns such as `import = require(...)` and namespace imports used like callable values.',
2258
+ },
2259
+ messages: {
2260
+ avoidCallableNamespaceImport: 'Namespace import "{{name}}" is used like a value instead of a namespace. This is a brittle interop pattern and often should become a default import.',
2261
+ avoidImportEquals: '`import {{name}} = require(...)` is a legacy CommonJS import pattern.',
2262
+ },
2263
+ schema: [],
2264
+ type: 'problem',
2265
+ },
2266
+ name: 'no-commonjs-import-patterns',
2267
+ });
2268
+
2144
2269
  const MESSAGE_ID$4 = 'no-deep-imports';
2145
2270
  const ERROR_MESSAGE$2 = 'Deep imports of Taiga UI packages are prohibited';
2146
2271
  const CODE_EXTENSIONS = new Set([
@@ -2160,8 +2285,8 @@ const DEFAULT_OPTIONS = {
2160
2285
  importDeclaration: '^@taiga-ui*',
2161
2286
  projectName: String.raw `(?<=^@taiga-ui/)([-\w]+)`,
2162
2287
  };
2163
- const createRule$e = ESLintUtils.RuleCreator((name) => name);
2164
- const rule$h = createRule$e({
2288
+ const createRule$h = ESLintUtils.RuleCreator((name) => name);
2289
+ const rule$k = createRule$h({
2165
2290
  create(context) {
2166
2291
  const { currentProject, deepImport, ignoreImports, importDeclaration, projectName, } = { ...DEFAULT_OPTIONS, ...context.options[0] };
2167
2292
  const hasNonCodeExtension = (source) => {
@@ -2248,13 +2373,13 @@ const rule$h = createRule$e({
2248
2373
  name: 'no-deep-imports',
2249
2374
  });
2250
2375
 
2251
- const createRule$d = ESLintUtils.RuleCreator((name) => name);
2376
+ const createRule$g = ESLintUtils.RuleCreator((name) => name);
2252
2377
  const resolveCacheByOptions = new WeakMap();
2253
2378
  const nearestFileUpCache = new Map();
2254
2379
  const markerCache = new Map();
2255
2380
  const indexFileCache = new Map();
2256
2381
  const indexExportsCache = new Map();
2257
- var noDeepImportsToIndexedPackages = createRule$d({
2382
+ var noDeepImportsToIndexedPackages = createRule$g({
2258
2383
  create(context) {
2259
2384
  const parserServices = ESLintUtils.getParserServices(context);
2260
2385
  const program = parserServices.program;
@@ -2443,63 +2568,13 @@ function stripKnownExtensions(filePathOrSpecifier) {
2443
2568
  return filePathOrSpecifier.replace(/\.(?:d\.ts|ts|tsx|js|jsx|mjs|cjs)$/, '');
2444
2569
  }
2445
2570
 
2446
- const ANGULAR_CORE$1 = '@angular/core';
2447
- /**
2448
- * Returns the local name bound to a named import from a given source.
2449
- * Handles aliased imports: `import { untracked as ngUntracked } from '@angular/core'`
2450
- * returns `'ngUntracked'` for `exportedName = 'untracked'`.
2451
- */
2452
- function getLocalNameForImport(program, source, exportedName) {
2453
- for (const node of program.body) {
2454
- if (node.type !== AST_NODE_TYPES.ImportDeclaration ||
2455
- node.source.value !== source) {
2456
- continue;
2457
- }
2458
- for (const spec of node.specifiers) {
2459
- if (spec.type !== AST_NODE_TYPES.ImportSpecifier) {
2460
- continue;
2461
- }
2462
- const imported = spec.imported.type === AST_NODE_TYPES.Identifier
2463
- ? spec.imported.name
2464
- : spec.imported.value;
2465
- if (imported === exportedName) {
2466
- return spec.local.name;
2467
- }
2468
- }
2469
- }
2470
- return null;
2471
- }
2472
- function findAngularCoreImports(program) {
2473
- return program.body.filter((node) => node.type === AST_NODE_TYPES.ImportDeclaration &&
2474
- node.source.value === ANGULAR_CORE$1);
2475
- }
2476
- function findRuntimeAngularCoreImport(program) {
2477
- return (findAngularCoreImports(program).find((node) => node.importKind !== 'type') ?? null);
2478
- }
2479
- function findAngularCoreImportSpecifier(program, exportedName) {
2480
- for (const importDecl of findAngularCoreImports(program)) {
2481
- for (const specifier of importDecl.specifiers) {
2482
- if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) {
2483
- continue;
2484
- }
2485
- const imported = specifier.imported.type === AST_NODE_TYPES.Identifier
2486
- ? specifier.imported.name
2487
- : specifier.imported.value;
2488
- if (imported === exportedName) {
2489
- return { importDecl, specifier };
2490
- }
2491
- }
2492
- }
2493
- return null;
2494
- }
2495
-
2496
- function isFunctionLike$1(node) {
2571
+ function isFunctionLike(node) {
2497
2572
  return (node.type === AST_NODE_TYPES.ArrowFunctionExpression ||
2498
2573
  node.type === AST_NODE_TYPES.FunctionDeclaration ||
2499
2574
  node.type === AST_NODE_TYPES.FunctionExpression);
2500
2575
  }
2501
2576
  function getOrderedChildren(node) {
2502
- if (isFunctionLike$1(node)) {
2577
+ if (isFunctionLike(node)) {
2503
2578
  const children = [
2504
2579
  ...node.params,
2505
2580
  node.body,
@@ -2568,7 +2643,7 @@ function getOrderedChildren(node) {
2568
2643
  function walkSynchronousAst(root, visitor) {
2569
2644
  traverse(root, true);
2570
2645
  function traverse(node, isRoot = false) {
2571
- if (visitor(node) === false || (!isRoot && isFunctionLike$1(node))) {
2646
+ if (visitor(node) === false || (!isRoot && isFunctionLike(node))) {
2572
2647
  return false;
2573
2648
  }
2574
2649
  if (node.type === AST_NODE_TYPES.AwaitExpression) {
@@ -2597,7 +2672,7 @@ function walkAfterAsyncBoundaryAst(root, visitor) {
2597
2672
  if (afterBoundary) {
2598
2673
  visitor(node);
2599
2674
  }
2600
- if (!isRoot && isFunctionLike$1(node)) {
2675
+ if (!isRoot && isFunctionLike(node)) {
2601
2676
  return false;
2602
2677
  }
2603
2678
  if (node.type === AST_NODE_TYPES.AwaitExpression) {
@@ -2660,6 +2735,56 @@ function walkAst(root, visitor) {
2660
2735
  }
2661
2736
  }
2662
2737
 
2738
+ const ANGULAR_CORE$1 = '@angular/core';
2739
+ /**
2740
+ * Returns the local name bound to a named import from a given source.
2741
+ * Handles aliased imports: `import { untracked as ngUntracked } from '@angular/core'`
2742
+ * returns `'ngUntracked'` for `exportedName = 'untracked'`.
2743
+ */
2744
+ function getLocalNameForImport(program, source, exportedName) {
2745
+ for (const node of program.body) {
2746
+ if (node.type !== AST_NODE_TYPES.ImportDeclaration ||
2747
+ node.source.value !== source) {
2748
+ continue;
2749
+ }
2750
+ for (const spec of node.specifiers) {
2751
+ if (spec.type !== AST_NODE_TYPES.ImportSpecifier) {
2752
+ continue;
2753
+ }
2754
+ const imported = spec.imported.type === AST_NODE_TYPES.Identifier
2755
+ ? spec.imported.name
2756
+ : spec.imported.value;
2757
+ if (imported === exportedName) {
2758
+ return spec.local.name;
2759
+ }
2760
+ }
2761
+ }
2762
+ return null;
2763
+ }
2764
+ function findAngularCoreImports(program) {
2765
+ return program.body.filter((node) => node.type === AST_NODE_TYPES.ImportDeclaration &&
2766
+ node.source.value === ANGULAR_CORE$1);
2767
+ }
2768
+ function findRuntimeAngularCoreImport(program) {
2769
+ return (findAngularCoreImports(program).find((node) => node.importKind !== 'type') ?? null);
2770
+ }
2771
+ function findAngularCoreImportSpecifier(program, exportedName) {
2772
+ for (const importDecl of findAngularCoreImports(program)) {
2773
+ for (const specifier of importDecl.specifiers) {
2774
+ if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) {
2775
+ continue;
2776
+ }
2777
+ const imported = specifier.imported.type === AST_NODE_TYPES.Identifier
2778
+ ? specifier.imported.name
2779
+ : specifier.imported.value;
2780
+ if (imported === exportedName) {
2781
+ return { importDecl, specifier };
2782
+ }
2783
+ }
2784
+ }
2785
+ return null;
2786
+ }
2787
+
2663
2788
  const ANGULAR_CORE = '@angular/core';
2664
2789
  const SIGNAL_WRITE_METHODS = new Set(['mutate', 'set', 'update']);
2665
2790
  const AFTER_RENDER_EFFECT_PHASES = new Map([
@@ -2668,10 +2793,14 @@ const AFTER_RENDER_EFFECT_PHASES = new Map([
2668
2793
  ['read', 'afterRenderEffect().read'],
2669
2794
  ['write', 'afterRenderEffect().write'],
2670
2795
  ]);
2671
- function isReactiveCallback$1(node) {
2796
+ function isReactiveCallback(node) {
2672
2797
  return (node?.type === AST_NODE_TYPES.ArrowFunctionExpression ||
2673
2798
  node?.type === AST_NODE_TYPES.FunctionExpression);
2674
2799
  }
2800
+ function getReactiveCallbackArgument(node) {
2801
+ const [arg] = node.arguments;
2802
+ return isReactiveCallback(arg) ? arg : null;
2803
+ }
2675
2804
  function getPropertyName(property) {
2676
2805
  if (property.computed) {
2677
2806
  return null;
@@ -2691,11 +2820,11 @@ function isAngularCoreCall(node, program, exportedName) {
2691
2820
  node.arguments.length >= 1);
2692
2821
  }
2693
2822
  function appendFirstArgReactiveScope(scopes, call, kind) {
2694
- const [arg] = call.arguments;
2695
- if (!isReactiveCallback$1(arg)) {
2823
+ const callback = getReactiveCallbackArgument(call);
2824
+ if (!callback) {
2696
2825
  return;
2697
2826
  }
2698
- scopes.push({ callback: arg, kind, owner: call, reportNode: call });
2827
+ scopes.push({ callback, kind, owner: call, reportNode: call });
2699
2828
  }
2700
2829
  function appendObjectPropertyReactiveScopes(scopes, call, object, labels) {
2701
2830
  for (const property of object.properties) {
@@ -2704,7 +2833,7 @@ function appendObjectPropertyReactiveScopes(scopes, call, object, labels) {
2704
2833
  }
2705
2834
  const name = getPropertyName(property);
2706
2835
  const label = name ? labels.get(name) : null;
2707
- if (!label || !isReactiveCallback$1(property.value)) {
2836
+ if (!label || !isReactiveCallback(property.value)) {
2708
2837
  continue;
2709
2838
  }
2710
2839
  scopes.push({
@@ -2914,54 +3043,74 @@ function collectSignalUsages(scopeNode, checker, esTreeNodeToTSNodeMap, program)
2914
3043
  });
2915
3044
  return { reads, writes };
2916
3045
  }
2917
-
2918
- const ANGULAR_SIGNALS_UNTRACKED_GUIDE_URL = 'https://angular.dev/guide/signals#reading-without-tracking-dependencies';
2919
- const ANGULAR_SIGNALS_ASYNC_GUIDE_URL = 'https://angular.dev/guide/signals#reactive-context-and-async-operations';
2920
- const UNTRACKED_RULES_README_URL = 'https://github.com/taiga-family/taiga-ui/blob/main/projects/eslint-plugin-experience-next/README.md';
2921
- const createUntrackedRule = ESLintUtils.RuleCreator((name) => `${UNTRACKED_RULES_README_URL}#${name}`);
2922
-
2923
- /**
2924
- * Collects signal reads that appear inside `untracked(...)` callbacks within
2925
- * `root`, without descending into nested `untracked(...)` scopes.
2926
- */
2927
- function collectReadsInsideUntracked(root, checker, esTreeNodeToTSNodeMap, program) {
3046
+ function collectSignalReadsInsideUntracked(root, checker, esTreeNodeToTSNodeMap, program) {
2928
3047
  const reads = [];
2929
3048
  walkSynchronousAst(root, (node) => {
2930
3049
  if (node.type !== AST_NODE_TYPES.CallExpression ||
2931
3050
  !isAngularUntrackedCall(node, program)) {
2932
3051
  return;
2933
3052
  }
2934
- const [arg] = node.arguments;
2935
- if (!arg ||
2936
- (arg.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
2937
- arg.type !== AST_NODE_TYPES.FunctionExpression)) {
3053
+ const callback = getReactiveCallbackArgument(node);
3054
+ if (!callback) {
2938
3055
  return false;
2939
3056
  }
2940
- walkSynchronousAst(arg, (inner) => {
3057
+ walkSynchronousAst(callback, (inner) => {
2941
3058
  if (inner.type === AST_NODE_TYPES.CallExpression &&
2942
3059
  isSignalReadCall(inner, checker, esTreeNodeToTSNodeMap)) {
2943
3060
  reads.push(inner);
2944
3061
  }
2945
3062
  });
2946
- return false; // Do not descend into nested untracked from the outer walk
3063
+ return false;
2947
3064
  });
2948
3065
  return reads;
2949
3066
  }
2950
- const rule$g = createUntrackedRule({
3067
+ function isReactiveOwnerCall(node, program) {
3068
+ return (node.type === AST_NODE_TYPES.CallExpression &&
3069
+ getReactiveScopes(node, program).length > 0);
3070
+ }
3071
+ function getReturnedReactiveOwnerCall(node, program) {
3072
+ const callback = getReactiveCallbackArgument(node);
3073
+ if (!callback) {
3074
+ return null;
3075
+ }
3076
+ if (isReactiveOwnerCall(callback.body, program)) {
3077
+ return callback.body;
3078
+ }
3079
+ if (callback.body.type !== AST_NODE_TYPES.BlockStatement ||
3080
+ callback.body.body.length !== 1) {
3081
+ return null;
3082
+ }
3083
+ const [statement] = callback.body.body;
3084
+ if (statement?.type === AST_NODE_TYPES.ReturnStatement &&
3085
+ statement.argument &&
3086
+ isReactiveOwnerCall(statement.argument, program)) {
3087
+ return statement.argument;
3088
+ }
3089
+ if (node.parent.type === AST_NODE_TYPES.ExpressionStatement &&
3090
+ statement?.type === AST_NODE_TYPES.ExpressionStatement &&
3091
+ isReactiveOwnerCall(statement.expression, program)) {
3092
+ return statement.expression;
3093
+ }
3094
+ return null;
3095
+ }
3096
+
3097
+ const ANGULAR_SIGNALS_UNTRACKED_GUIDE_URL = 'https://angular.dev/guide/signals#reading-without-tracking-dependencies';
3098
+ const ANGULAR_SIGNALS_ASYNC_GUIDE_URL = 'https://angular.dev/guide/signals#reactive-context-and-async-operations';
3099
+ const UNTRACKED_RULES_README_URL = 'https://github.com/taiga-family/taiga-ui/blob/main/projects/eslint-plugin-experience-next/README.md';
3100
+ const createUntrackedRule = ESLintUtils.RuleCreator((name) => `${UNTRACKED_RULES_README_URL}#${name}`);
3101
+
3102
+ const rule$j = createUntrackedRule({
2951
3103
  create(context) {
2952
- const parserServices = ESLintUtils.getParserServices(context);
2953
- const checker = parserServices.program.getTypeChecker();
2954
- const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
2955
- const { sourceCode } = context;
2956
- const program = sourceCode.ast;
3104
+ const { checker, esTreeNodeToTSNodeMap, program } = getTypeAwareRuleContext(context);
3105
+ const signalNodeMap = esTreeNodeToTSNodeMap;
2957
3106
  return {
2958
3107
  CallExpression(node) {
2959
3108
  for (const scope of getReactiveScopes(node, program)) {
2960
- const { reads: trackedReads } = collectSignalUsages(scope.callback, checker, esTreeNodeToTSNodeMap, program);
3109
+ const { reads: trackedReads } = collectSignalUsages(scope.callback, checker, signalNodeMap, program);
2961
3110
  if (trackedReads.length > 0) {
2962
3111
  continue;
2963
3112
  }
2964
- const untrackedReads = collectReadsInsideUntracked(scope.callback, checker, esTreeNodeToTSNodeMap, program);
3113
+ const untrackedReads = collectSignalReadsInsideUntracked(scope.callback, checker, signalNodeMap, program);
2965
3114
  if (untrackedReads.length === 0) {
2966
3115
  continue;
2967
3116
  }
@@ -3033,11 +3182,67 @@ const config$1 = {
3033
3182
  },
3034
3183
  };
3035
3184
 
3036
- const createRule$c = ESLintUtils.RuleCreator((name) => name);
3037
- const rule$f = createRule$c({
3185
+ function findAncestor(node, predicate) {
3186
+ for (let current = node?.parent; current; current = current.parent) {
3187
+ if (predicate(current)) {
3188
+ return current;
3189
+ }
3190
+ }
3191
+ return null;
3192
+ }
3193
+ function findSelfOrAncestor(node, predicate) {
3194
+ for (let current = node; current; current = current.parent) {
3195
+ if (predicate(current)) {
3196
+ return current;
3197
+ }
3198
+ }
3199
+ return null;
3200
+ }
3201
+ function hasAncestor(node, predicate) {
3202
+ for (let current = node?.parent; current; current = current.parent) {
3203
+ if (predicate(current)) {
3204
+ return true;
3205
+ }
3206
+ }
3207
+ return false;
3208
+ }
3209
+ function isNodeInside(node, ancestor) {
3210
+ for (let current = node; current; current = current.parent) {
3211
+ if (current === ancestor) {
3212
+ return true;
3213
+ }
3214
+ }
3215
+ return false;
3216
+ }
3217
+ function isNodeInsideAny(node, ancestors) {
3218
+ return ancestors.some((ancestor) => isNodeInside(node, ancestor));
3219
+ }
3220
+ function isClassLike(node) {
3221
+ return (node.type === AST_NODE_TYPES.ClassDeclaration ||
3222
+ node.type === AST_NODE_TYPES.ClassExpression);
3223
+ }
3224
+ function isClassMember(node) {
3225
+ return (node.type === AST_NODE_TYPES.MethodDefinition ||
3226
+ node.type === AST_NODE_TYPES.PropertyDefinition);
3227
+ }
3228
+ function getEnclosingFunction(node) {
3229
+ return findAncestor(node, isFunctionLike);
3230
+ }
3231
+ function getEnclosingClass(node) {
3232
+ return findSelfOrAncestor(node, isClassLike);
3233
+ }
3234
+ function getEnclosingClassMember(node) {
3235
+ return findAncestor(node, isClassMember);
3236
+ }
3237
+ function getScopeRoot(node) {
3238
+ return (findAncestor(node, (ancestor) => ancestor.type === AST_NODE_TYPES.Program || isFunctionLike(ancestor)) ?? node);
3239
+ }
3240
+
3241
+ const createRule$f = ESLintUtils.RuleCreator((name) => name);
3242
+ const rule$i = createRule$f({
3038
3243
  create(context) {
3039
3244
  const checkImplicitPublic = (node) => {
3040
- const classRef = getClass(node);
3245
+ const classRef = getEnclosingClass(node);
3041
3246
  if (!classRef ||
3042
3247
  node.kind === 'constructor' ||
3043
3248
  !!node?.accessibility ||
@@ -3095,19 +3300,114 @@ const rule$f = createRule$c({
3095
3300
  },
3096
3301
  name: 'explicit-public-member',
3097
3302
  });
3098
- function getClass(node) {
3099
- if (!node) {
3100
- return null;
3303
+
3304
+ const createRule$e = ESLintUtils.RuleCreator((name) => name);
3305
+ const rule$h = createRule$e({
3306
+ create(context) {
3307
+ const { sourceCode } = context;
3308
+ return {
3309
+ ImportDeclaration(node) {
3310
+ const importAttributesToken = sourceCode.getTokenAfter(node.source);
3311
+ if (importAttributesToken?.value !== 'assert') {
3312
+ return;
3313
+ }
3314
+ context.report({
3315
+ fix: (fixer) => fixer.replaceText(importAttributesToken, 'with'),
3316
+ messageId: 'useWithImportAttributes',
3317
+ node: importAttributesToken,
3318
+ });
3319
+ },
3320
+ };
3321
+ },
3322
+ meta: {
3323
+ docs: {
3324
+ description: 'Disallow legacy `assert { ... }` import assertions. Use `with { ... }` import attributes instead.',
3325
+ },
3326
+ fixable: 'code',
3327
+ messages: {
3328
+ useWithImportAttributes: 'Use `with { ... }` import attributes instead of `assert { ... }`.',
3329
+ },
3330
+ schema: [],
3331
+ type: 'problem',
3332
+ },
3333
+ name: 'no-import-assertions',
3334
+ });
3335
+
3336
+ function getParenthesizedInner(node) {
3337
+ const maybeNode = node;
3338
+ if (maybeNode.type === 'ParenthesizedExpression') {
3339
+ return maybeNode.expression ?? null;
3101
3340
  }
3102
- if (node.type === AST_NODE_TYPES.ClassDeclaration) {
3103
- return node;
3341
+ return null;
3342
+ }
3343
+ function unwrapParenthesized(node) {
3344
+ let current = node;
3345
+ let inner = getParenthesizedInner(current);
3346
+ while (inner) {
3347
+ current = inner;
3348
+ inner = getParenthesizedInner(current);
3104
3349
  }
3105
- return getClass(node.parent);
3350
+ return current;
3106
3351
  }
3107
3352
 
3108
- const createRule$b = ESLintUtils.RuleCreator((name) => name);
3353
+ const createRule$d = ESLintUtils.RuleCreator((name) => name);
3354
+ function isInfiniteLoopLiteral(node) {
3355
+ const unwrapped = unwrapParenthesized(node);
3356
+ if (unwrapped.type !== AST_NODE_TYPES.Literal) {
3357
+ return false;
3358
+ }
3359
+ return unwrapped.value === true || unwrapped.value === 1;
3360
+ }
3361
+ function isInfiniteLoopTest(test) {
3362
+ return test === null || isInfiniteLoopLiteral(test);
3363
+ }
3364
+ const rule$g = createRule$d({
3365
+ create(context) {
3366
+ return {
3367
+ DoWhileStatement(node) {
3368
+ if (isInfiniteLoopTest(node.test)) {
3369
+ context.report({
3370
+ messageId: 'doWhileLoop',
3371
+ node: node.test,
3372
+ });
3373
+ }
3374
+ },
3375
+ ForStatement(node) {
3376
+ if (isInfiniteLoopTest(node.test)) {
3377
+ context.report({
3378
+ messageId: 'forLoop',
3379
+ node,
3380
+ });
3381
+ }
3382
+ },
3383
+ WhileStatement(node) {
3384
+ if (isInfiniteLoopTest(node.test)) {
3385
+ context.report({
3386
+ messageId: 'whileLoop',
3387
+ node: node.test,
3388
+ });
3389
+ }
3390
+ },
3391
+ };
3392
+ },
3393
+ meta: {
3394
+ docs: {
3395
+ description: 'Disallow `for (;;)` / conditionals `for`, `while (true)`, and `do ... while (true)`. Prefer loops with meaningful exit conditions.',
3396
+ },
3397
+ messages: {
3398
+ doWhileLoop: 'Use an explicit exit condition instead of `do ... while (true)`.',
3399
+ forLoop: 'Use an explicit exit condition instead of a `for` loop without a condition.',
3400
+ whileLoop: 'Use an explicit exit condition instead of `while (true)`.',
3401
+ },
3402
+ schema: [],
3403
+ type: 'suggestion',
3404
+ },
3405
+ name: 'no-infinite-loop',
3406
+ });
3407
+
3408
+ const createRule$c = ESLintUtils.RuleCreator((name) => name);
3109
3409
  const LEGACY_PEER_DEPS_PATTERN = /^legacy-peer-deps\s*=\s*true$/i;
3110
- const rule$e = createRule$b({
3410
+ const rule$f = createRule$c({
3111
3411
  create(context) {
3112
3412
  return {
3113
3413
  Program(node) {
@@ -3145,11 +3445,10 @@ const rule$e = createRule$b({
3145
3445
  name: 'no-legacy-peer-deps',
3146
3446
  });
3147
3447
 
3148
- const createRule$a = ESLintUtils.RuleCreator((name) => name);
3149
- const rule$d = createRule$a({
3448
+ const createRule$b = ESLintUtils.RuleCreator((name) => name);
3449
+ const rule$e = createRule$b({
3150
3450
  create(context) {
3151
- const services = ESLintUtils.getParserServices(context);
3152
- const checker = services.program.getTypeChecker();
3451
+ const { checker, esTreeNodeToTSNodeMap, sourceCode } = getTypeAwareRuleContext(context);
3153
3452
  return {
3154
3453
  CallExpression(node) {
3155
3454
  const callee = node.callee;
@@ -3163,18 +3462,18 @@ const rule$d = createRule$a({
3163
3462
  return;
3164
3463
  }
3165
3464
  const [argument] = node.arguments;
3166
- if (!argument || !isEmptyString(argument)) {
3465
+ if (!argument || !isEmptyStaticString(argument)) {
3167
3466
  return;
3168
3467
  }
3169
3468
  const objectExpression = callee.object;
3170
- const tsNode = services.esTreeNodeToTSNodeMap.get(objectExpression);
3469
+ const tsNode = esTreeNodeToTSNodeMap.get(objectExpression);
3171
3470
  const type = checker.getTypeAtLocation(tsNode);
3172
3471
  if (!isPlaywrightLocator(type, checker)) {
3173
3472
  return;
3174
3473
  }
3175
3474
  context.report({
3176
3475
  fix(fixer) {
3177
- const objectText = context.sourceCode.getText(objectExpression);
3476
+ const objectText = sourceCode.getText(objectExpression);
3178
3477
  return fixer.replaceText(node, `${objectText}.clear()`);
3179
3478
  },
3180
3479
  messageId: 'useClear',
@@ -3194,13 +3493,6 @@ const rule$d = createRule$a({
3194
3493
  },
3195
3494
  name: 'no-playwright-empty-fill',
3196
3495
  });
3197
- function isEmptyString(node) {
3198
- return ((node.type === AST_NODE_TYPES$1.Literal && node.value === '') ||
3199
- (node.type === AST_NODE_TYPES$1.TemplateLiteral &&
3200
- node.expressions.length === 0 &&
3201
- node.quasis.length === 1 &&
3202
- node.quasis[0]?.value.cooked === ''));
3203
- }
3204
3496
  function isPlaywrightLocator(type, checker) {
3205
3497
  if (isPlaywrightLocatorType(type)) {
3206
3498
  return true;
@@ -3311,7 +3603,7 @@ const config = {
3311
3603
  },
3312
3604
  };
3313
3605
 
3314
- const createRule$9 = ESLintUtils.RuleCreator((name) => name);
3606
+ const createRule$a = ESLintUtils.RuleCreator((name) => name);
3315
3607
  function collectArrayExpressions(node) {
3316
3608
  const result = [];
3317
3609
  if (node.type === AST_NODE_TYPES.ArrayExpression) {
@@ -3337,17 +3629,16 @@ function collectArrayExpressions(node) {
3337
3629
  }
3338
3630
  return result;
3339
3631
  }
3340
- const rule$c = createRule$9({
3632
+ const rule$d = createRule$a({
3341
3633
  create(context) {
3342
- const parserServices = ESLintUtils.getParserServices(context);
3343
- const typeChecker = parserServices.program.getTypeChecker();
3634
+ const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
3344
3635
  const ignoreTupleContextualTyping = context.options[0]?.ignoreTupleContextualTyping ?? true;
3345
3636
  function check(node, typeAnnotation, value) {
3346
3637
  if (!typeAnnotation || !value) {
3347
3638
  return;
3348
3639
  }
3349
- const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
3350
- const tsValueNode = parserServices.esTreeNodeToTSNodeMap.get(value);
3640
+ const tsNode = esTreeNodeToTSNodeMap.get(node);
3641
+ const tsValueNode = esTreeNodeToTSNodeMap.get(value);
3351
3642
  const declaredType = typeChecker.getTypeAtLocation(tsNode);
3352
3643
  const inferredType = typeChecker.getTypeAtLocation(tsValueNode);
3353
3644
  if (typeChecker.typeToString(declaredType) !==
@@ -3371,7 +3662,7 @@ const rule$c = createRule$9({
3371
3662
  if (ignoreTupleContextualTyping) {
3372
3663
  const arrayExpressions = collectArrayExpressions(value);
3373
3664
  for (const arrayExpression of arrayExpressions) {
3374
- const tsArrayNode = parserServices.esTreeNodeToTSNodeMap.get(arrayExpression);
3665
+ const tsArrayNode = esTreeNodeToTSNodeMap.get(arrayExpression);
3375
3666
  if (typeChecker.isTupleType(typeChecker.getTypeAtLocation(tsArrayNode))) {
3376
3667
  return;
3377
3668
  }
@@ -3465,16 +3756,6 @@ function unwrapExpression(expression) {
3465
3756
  return current;
3466
3757
  }
3467
3758
 
3468
- const createRule$8 = ESLintUtils.RuleCreator((name) => name);
3469
- function isFunctionLikeScope(node) {
3470
- return (node?.type === AST_NODE_TYPES.ArrowFunctionExpression ||
3471
- node?.type === AST_NODE_TYPES.FunctionDeclaration ||
3472
- node?.type === AST_NODE_TYPES.FunctionExpression);
3473
- }
3474
- function isReactiveCallback(node) {
3475
- return (node?.type === AST_NODE_TYPES.ArrowFunctionExpression ||
3476
- node?.type === AST_NODE_TYPES.FunctionExpression);
3477
- }
3478
3759
  function unwrapMutationTarget(node) {
3479
3760
  let current = node;
3480
3761
  while (current.type === AST_NODE_TYPES.TSAsExpression ||
@@ -3508,6 +3789,7 @@ function collectMutationTargets(node) {
3508
3789
  return [];
3509
3790
  }
3510
3791
  }
3792
+
3511
3793
  function getSymbolAtNode(node, checker, esTreeNodeToTSNodeMap) {
3512
3794
  const tsNode = esTreeNodeToTSNodeMap.get(node);
3513
3795
  if (!tsNode) {
@@ -3515,6 +3797,11 @@ function getSymbolAtNode(node, checker, esTreeNodeToTSNodeMap) {
3515
3797
  }
3516
3798
  return checker.getSymbolAtLocation(tsNode) ?? null;
3517
3799
  }
3800
+
3801
+ const createRule$9 = ESLintUtils.RuleCreator((name) => name);
3802
+ function isFunctionLikeScope(node) {
3803
+ return !!node && isFunctionLike(node);
3804
+ }
3518
3805
  function isLocalIdentifier(node, context, localScopes) {
3519
3806
  const symbol = getSymbolAtNode(node, context.checker, context.esTreeNodeToTSNodeMap);
3520
3807
  if (!symbol) {
@@ -3671,9 +3958,9 @@ function functionHasObservableSideEffects(root, context, localScopes, visitedFun
3671
3958
  return false;
3672
3959
  }
3673
3960
  if (isAngularUntrackedCall(node, context.program)) {
3674
- const [arg] = node.arguments;
3675
- if (isReactiveCallback(arg) &&
3676
- functionHasObservableSideEffects(arg, context, [...localScopes, arg], visitedFunctions)) {
3961
+ const callback = getReactiveCallbackArgument(node);
3962
+ if (callback &&
3963
+ functionHasObservableSideEffects(callback, context, [...localScopes, callback], visitedFunctions)) {
3677
3964
  hasSideEffect = true;
3678
3965
  }
3679
3966
  return false;
@@ -3727,9 +4014,9 @@ function inspectComputedBody(root, context, localScopes, visitedFunctions, repor
3727
4014
  return false;
3728
4015
  }
3729
4016
  if (isAngularUntrackedCall(node, context.program)) {
3730
- const [arg] = node.arguments;
3731
- if (isReactiveCallback(arg)) {
3732
- inspectComputedBody(arg, context, [...localScopes, arg], visitedFunctions, report);
4017
+ const callback = getReactiveCallbackArgument(node);
4018
+ if (callback) {
4019
+ inspectComputedBody(callback, context, [...localScopes, callback], visitedFunctions, report);
3733
4020
  }
3734
4021
  return false;
3735
4022
  }
@@ -3768,14 +4055,11 @@ function inspectComputedBody(root, context, localScopes, visitedFunctions, repor
3768
4055
  return;
3769
4056
  });
3770
4057
  }
3771
- const rule$b = createRule$8({
4058
+ const rule$c = createRule$9({
3772
4059
  create(context) {
3773
- const parserServices = ESLintUtils.getParserServices(context);
3774
- const checker = parserServices.program.getTypeChecker();
3775
- const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
3776
- const tsNodeToESTreeNodeMap = parserServices.tsNodeToESTreeNodeMap;
3777
- const { sourceCode } = context;
3778
- const program = sourceCode.ast;
4060
+ const { checker, esTreeNodeToTSNodeMap, program, sourceCode, tsNodeToESTreeNodeMap, } = getTypeAwareRuleContext(context);
4061
+ const signalNodeMap = esTreeNodeToTSNodeMap;
4062
+ const estreeNodeMap = tsNodeToESTreeNodeMap;
3779
4063
  return {
3780
4064
  CallExpression(node) {
3781
4065
  for (const scope of getReactiveScopes(node, program)) {
@@ -3784,10 +4068,10 @@ const rule$b = createRule$8({
3784
4068
  }
3785
4069
  const analysisContext = {
3786
4070
  checker,
3787
- esTreeNodeToTSNodeMap,
4071
+ esTreeNodeToTSNodeMap: signalNodeMap,
3788
4072
  program,
3789
4073
  reported: new Set(),
3790
- tsNodeToESTreeNodeMap,
4074
+ tsNodeToESTreeNodeMap: estreeNodeMap,
3791
4075
  };
3792
4076
  inspectComputedBody(scope.callback, analysisContext, [scope.callback], new Set([String(scope.callback.range)]), (reportNode) => {
3793
4077
  context.report({
@@ -3814,13 +4098,10 @@ const rule$b = createRule$8({
3814
4098
  name: 'no-side-effects-in-computed',
3815
4099
  });
3816
4100
 
3817
- const rule$a = createUntrackedRule({
4101
+ const rule$b = createUntrackedRule({
3818
4102
  create(context) {
3819
- const parserServices = ESLintUtils.getParserServices(context);
3820
- const checker = parserServices.program.getTypeChecker();
3821
- const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
3822
- const { sourceCode } = context;
3823
- const program = sourceCode.ast;
4103
+ const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
4104
+ const signalNodeMap = esTreeNodeToTSNodeMap;
3824
4105
  return {
3825
4106
  CallExpression(node) {
3826
4107
  for (const scope of getReactiveScopes(node, program)) {
@@ -3828,7 +4109,7 @@ const rule$a = createUntrackedRule({
3828
4109
  walkAfterAsyncBoundaryAst(scope.callback, (inner) => {
3829
4110
  if (inner.type !== AST_NODE_TYPES.CallExpression ||
3830
4111
  isAngularUntrackedCall(inner, program) ||
3831
- !isSignalReadCall(inner, checker, esTreeNodeToTSNodeMap)) {
4112
+ !isSignalReadCall(inner, checker, signalNodeMap)) {
3832
4113
  return;
3833
4114
  }
3834
4115
  const key = String(inner.range);
@@ -3863,11 +4144,7 @@ const rule$a = createUntrackedRule({
3863
4144
  name: 'no-signal-reads-after-await-in-reactive-context',
3864
4145
  });
3865
4146
 
3866
- const createRule$7 = ESLintUtils.RuleCreator((name) => name);
3867
- function isStringLiteral(node) {
3868
- return (node.type === AST_NODE_TYPES.Literal &&
3869
- typeof node.value === 'string');
3870
- }
4147
+ const createRule$8 = ESLintUtils.RuleCreator((name) => name);
3871
4148
  function collectParts(node) {
3872
4149
  if (node.type === AST_NODE_TYPES.BinaryExpression && node.operator === '+') {
3873
4150
  return [...collectParts(node.left), ...collectParts(node.right)];
@@ -3917,17 +4194,7 @@ function templateContent(template, renderExpr) {
3917
4194
  : ''}`)
3918
4195
  .join('');
3919
4196
  }
3920
- function hasTemplateLiteralAncestor(node) {
3921
- let current = node.parent;
3922
- while (current != null) {
3923
- if (current.type === AST_NODE_TYPES.TemplateLiteral) {
3924
- return true;
3925
- }
3926
- current = current.parent;
3927
- }
3928
- return false;
3929
- }
3930
- const rule$9 = createRule$7({
4197
+ const rule$a = createRule$8({
3931
4198
  create(context) {
3932
4199
  const { sourceCode } = context;
3933
4200
  let parserServices = null;
@@ -3982,7 +4249,7 @@ const rule$9 = createRule$7({
3982
4249
  }
3983
4250
  // Nested inside a template but not direct child — would produce
3984
4251
  // `${`${a}${b}`.method()}`, so skip
3985
- if (hasTemplateLiteralAncestor(node)) {
4252
+ if (hasAncestor(node, (ancestor) => ancestor.type === AST_NODE_TYPES.TemplateLiteral)) {
3986
4253
  return;
3987
4254
  }
3988
4255
  context.report({
@@ -4096,67 +4363,6 @@ function buildImportRemovalFixes(program, fixer, sourceCode) {
4096
4363
  return [fixer.remove(untrackedSpec)];
4097
4364
  }
4098
4365
 
4099
- const IMPERATIVE_UNTRACKED_METHODS = new Set(['registerOnChange', 'writeValue']);
4100
- function dedent$1(text, extraSpaces) {
4101
- if (extraSpaces <= 0) {
4102
- return text;
4103
- }
4104
- const prefix = ' '.repeat(extraSpaces);
4105
- return text
4106
- .split('\n')
4107
- .map((line) => (line.startsWith(prefix) ? line.slice(extraSpaces) : line))
4108
- .join('\n');
4109
- }
4110
- function isFunctionLike(node) {
4111
- return (node.type === AST_NODE_TYPES.ArrowFunctionExpression ||
4112
- node.type === AST_NODE_TYPES.FunctionDeclaration ||
4113
- node.type === AST_NODE_TYPES.FunctionExpression);
4114
- }
4115
- function getObjectPropertyName(node) {
4116
- if (node.computed) {
4117
- return null;
4118
- }
4119
- if (node.key.type === AST_NODE_TYPES.Identifier) {
4120
- return node.key.name;
4121
- }
4122
- return typeof node.key.value === 'string' ? node.key.value : null;
4123
- }
4124
- function getMemberExpressionPropertyName(node) {
4125
- if (!node.computed && node.property.type === AST_NODE_TYPES.Identifier) {
4126
- return node.property.name;
4127
- }
4128
- return node.property.type === AST_NODE_TYPES.Literal &&
4129
- typeof node.property.value === 'string'
4130
- ? node.property.value
4131
- : null;
4132
- }
4133
- function getEnclosingClassMember(node) {
4134
- for (let current = node.parent; current; current = current.parent) {
4135
- if (current.type === AST_NODE_TYPES.MethodDefinition ||
4136
- current.type === AST_NODE_TYPES.PropertyDefinition) {
4137
- return current;
4138
- }
4139
- }
4140
- return null;
4141
- }
4142
- function getEnclosingFunction(node) {
4143
- for (let current = node.parent; current; current = current.parent) {
4144
- if (isFunctionLike(current)) {
4145
- return current;
4146
- }
4147
- }
4148
- return null;
4149
- }
4150
- function getClassMemberName(member) {
4151
- if (member.key.type === AST_NODE_TYPES.Identifier) {
4152
- return member.key.name;
4153
- }
4154
- if (member.key.type === AST_NODE_TYPES.Literal &&
4155
- typeof member.key.value === 'string') {
4156
- return member.key.value;
4157
- }
4158
- return null;
4159
- }
4160
4366
  function hasNamedDecorator(node, name) {
4161
4367
  return node.decorators.some((decorator) => {
4162
4368
  const expression = decorator.expression;
@@ -4168,68 +4374,75 @@ function hasNamedDecorator(node, name) {
4168
4374
  expression.callee.name === name);
4169
4375
  });
4170
4376
  }
4377
+
4171
4378
  function isPipeTransformMember(member) {
4172
4379
  if (getClassMemberName(member) !== 'transform') {
4173
4380
  return false;
4174
4381
  }
4175
- return hasNamedDecorator(member.parent.parent, 'Pipe');
4382
+ const ownerClass = getEnclosingClass(member);
4383
+ return !!ownerClass && hasNamedDecorator(ownerClass, 'Pipe');
4176
4384
  }
4177
- function hasAllowedImperativeAssignment(node) {
4178
- for (let current = node.parent; current; current = current.parent) {
4179
- if (!isFunctionLike(current)) {
4180
- continue;
4181
- }
4182
- const parent = current.parent;
4183
- if (parent.type === AST_NODE_TYPES.AssignmentExpression &&
4184
- parent.right === current &&
4185
- parent.left.type === AST_NODE_TYPES.MemberExpression) {
4186
- const memberName = getMemberExpressionPropertyName(parent.left);
4187
- if (memberName && IMPERATIVE_UNTRACKED_METHODS.has(memberName)) {
4188
- return true;
4189
- }
4190
- }
4385
+
4386
+ function isAngularInjectionTokenFactoryFunction(fn, program) {
4387
+ const parent = fn.parent;
4388
+ const injectionTokenName = getLocalNameForImport(program, '@angular/core', 'InjectionToken');
4389
+ if (!injectionTokenName ||
4390
+ parent.type !== AST_NODE_TYPES.Property ||
4391
+ getObjectPropertyName(parent) !== 'factory') {
4392
+ return false;
4191
4393
  }
4192
- return false;
4193
- }
4194
- function isAllowedImperativeAngularContext(node) {
4195
- const member = getEnclosingClassMember(node);
4196
- const memberName = member ? getClassMemberName(member) : null;
4197
- return ((!!member &&
4198
- !!memberName &&
4199
- (IMPERATIVE_UNTRACKED_METHODS.has(memberName) ||
4200
- isPipeTransformMember(member))) ||
4201
- hasAllowedImperativeAssignment(node));
4394
+ const objectExpression = parent.parent;
4395
+ return (objectExpression.type === AST_NODE_TYPES.ObjectExpression &&
4396
+ objectExpression.parent.type === AST_NODE_TYPES.NewExpression &&
4397
+ objectExpression.parent.arguments.includes(objectExpression) &&
4398
+ objectExpression.parent.callee.type === AST_NODE_TYPES.Identifier &&
4399
+ objectExpression.parent.callee.name === injectionTokenName);
4202
4400
  }
4203
- function isDirectCallbackArgument(fn) {
4401
+ function isAngularUseFactoryFunction(fn) {
4204
4402
  const parent = fn.parent;
4205
- if (fn.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
4206
- fn.type !== AST_NODE_TYPES.FunctionExpression) {
4403
+ if (parent.type !== AST_NODE_TYPES.Property ||
4404
+ getObjectPropertyName(parent) !== 'useFactory') {
4207
4405
  return false;
4208
4406
  }
4209
- return ((parent.type === AST_NODE_TYPES.CallExpression ||
4210
- parent.type === AST_NODE_TYPES.NewExpression) &&
4211
- parent.arguments.includes(fn));
4407
+ const objectExpression = parent.parent;
4408
+ return (objectExpression.type === AST_NODE_TYPES.ObjectExpression &&
4409
+ objectExpression.properties.some((property) => property.type === AST_NODE_TYPES.Property &&
4410
+ getObjectPropertyName(property) === 'provide'));
4212
4411
  }
4213
- function getScopeRoot(node) {
4214
- for (let current = node.parent; current; current = current.parent) {
4215
- if (current.type === AST_NODE_TYPES.Program || isFunctionLike(current)) {
4216
- return current;
4217
- }
4412
+
4413
+ /**
4414
+ * Removes `extraSpaces` leading spaces from every line of `text` that starts
4415
+ * with at least that many spaces.
4416
+ */
4417
+ function dedent(text, extraSpaces) {
4418
+ if (extraSpaces <= 0) {
4419
+ return text;
4218
4420
  }
4219
- return node;
4421
+ const prefix = ' '.repeat(extraSpaces);
4422
+ return text
4423
+ .split('\n')
4424
+ .map((line) => (line.startsWith(prefix) ? line.slice(extraSpaces) : line))
4425
+ .join('\n');
4426
+ }
4427
+
4428
+ function isDirectCallOrNewArgument(node) {
4429
+ const parent = node.parent;
4430
+ if (node.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
4431
+ node.type !== AST_NODE_TYPES.FunctionExpression) {
4432
+ return false;
4433
+ }
4434
+ return ((parent.type === AST_NODE_TYPES.CallExpression ||
4435
+ parent.type === AST_NODE_TYPES.NewExpression) &&
4436
+ parent.arguments.includes(node));
4220
4437
  }
4221
- function isStoredCallbackUsedAsArgument(fn, checker, esTreeNodeToTSNodeMap) {
4438
+ function isStoredFunctionUsedAsCallOrNewArgument(fn, checker, esTreeNodeToTSNodeMap) {
4222
4439
  const parent = fn.parent;
4223
4440
  if (parent.type !== AST_NODE_TYPES.VariableDeclarator ||
4224
4441
  parent.id.type !== AST_NODE_TYPES.Identifier) {
4225
4442
  return false;
4226
4443
  }
4227
4444
  const id = parent.id;
4228
- const tsNode = esTreeNodeToTSNodeMap.get(id);
4229
- if (!tsNode) {
4230
- return false;
4231
- }
4232
- const symbol = checker.getSymbolAtLocation(tsNode);
4445
+ const symbol = getSymbolAtNode(id, checker, esTreeNodeToTSNodeMap);
4233
4446
  if (!symbol) {
4234
4447
  return false;
4235
4448
  }
@@ -4241,10 +4454,7 @@ function isStoredCallbackUsedAsArgument(fn, checker, esTreeNodeToTSNodeMap) {
4241
4454
  node.name !== id.name) {
4242
4455
  return;
4243
4456
  }
4244
- const referenceTsNode = esTreeNodeToTSNodeMap.get(node);
4245
- const referenceSymbol = referenceTsNode
4246
- ? checker.getSymbolAtLocation(referenceTsNode)
4247
- : null;
4457
+ const referenceSymbol = getSymbolAtNode(node, checker, esTreeNodeToTSNodeMap);
4248
4458
  if (referenceSymbol !== symbol) {
4249
4459
  return;
4250
4460
  }
@@ -4259,81 +4469,50 @@ function isStoredCallbackUsedAsArgument(fn, checker, esTreeNodeToTSNodeMap) {
4259
4469
  });
4260
4470
  return found;
4261
4471
  }
4472
+
4473
+ const IMPERATIVE_UNTRACKED_METHODS = new Set(['registerOnChange', 'writeValue']);
4474
+ function hasAllowedImperativeAssignment(node) {
4475
+ for (let current = node.parent; current; current = current.parent) {
4476
+ if (current.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
4477
+ current.type !== AST_NODE_TYPES.FunctionDeclaration &&
4478
+ current.type !== AST_NODE_TYPES.FunctionExpression) {
4479
+ continue;
4480
+ }
4481
+ const parent = current.parent;
4482
+ if (parent.type === AST_NODE_TYPES.AssignmentExpression &&
4483
+ parent.right === current &&
4484
+ parent.left.type === AST_NODE_TYPES.MemberExpression) {
4485
+ const memberName = getMemberExpressionPropertyName(parent.left);
4486
+ if (memberName && IMPERATIVE_UNTRACKED_METHODS.has(memberName)) {
4487
+ return true;
4488
+ }
4489
+ }
4490
+ }
4491
+ return false;
4492
+ }
4493
+ function isAllowedImperativeAngularContext(node) {
4494
+ const member = getEnclosingClassMember(node);
4495
+ const memberName = member ? getClassMemberName(member) : null;
4496
+ return ((!!member &&
4497
+ !!memberName &&
4498
+ (IMPERATIVE_UNTRACKED_METHODS.has(memberName) ||
4499
+ isPipeTransformMember(member))) ||
4500
+ hasAllowedImperativeAssignment(node));
4501
+ }
4262
4502
  function isAllowedDeferredCallbackContext(node, checker, esTreeNodeToTSNodeMap) {
4263
- const [arg] = node.arguments;
4264
- if (!arg ||
4265
- arg.type === AST_NODE_TYPES.SpreadElement ||
4266
- (arg.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
4267
- arg.type !== AST_NODE_TYPES.FunctionExpression)) {
4503
+ if (!getReactiveCallbackArgument(node)) {
4268
4504
  return false;
4269
4505
  }
4270
4506
  const fn = getEnclosingFunction(node);
4271
4507
  if (!fn) {
4272
4508
  return false;
4273
4509
  }
4274
- return (isDirectCallbackArgument(fn) ||
4275
- isStoredCallbackUsedAsArgument(fn, checker, esTreeNodeToTSNodeMap));
4276
- }
4277
- function isAngularInjectionTokenFactoryFunction(fn, program) {
4278
- const parent = fn.parent;
4279
- const injectionTokenName = getLocalNameForImport(program, '@angular/core', 'InjectionToken');
4280
- if (!injectionTokenName ||
4281
- parent.type !== AST_NODE_TYPES.Property ||
4282
- getObjectPropertyName(parent) !== 'factory') {
4283
- return false;
4284
- }
4285
- const objectExpression = parent.parent;
4286
- return (objectExpression.type === AST_NODE_TYPES.ObjectExpression &&
4287
- objectExpression.parent.type === AST_NODE_TYPES.NewExpression &&
4288
- objectExpression.parent.arguments.includes(objectExpression) &&
4289
- objectExpression.parent.callee.type === AST_NODE_TYPES.Identifier &&
4290
- objectExpression.parent.callee.name === injectionTokenName);
4291
- }
4292
- function isAngularUseFactoryFunction(fn) {
4293
- const parent = fn.parent;
4294
- if (parent.type !== AST_NODE_TYPES.Property ||
4295
- getObjectPropertyName(parent) !== 'useFactory') {
4296
- return false;
4297
- }
4298
- const objectExpression = parent.parent;
4299
- return (objectExpression.type === AST_NODE_TYPES.ObjectExpression &&
4300
- objectExpression.properties.some((property) => property.type === AST_NODE_TYPES.Property &&
4301
- getObjectPropertyName(property) === 'provide'));
4302
- }
4303
- function isReactiveOwnerCall(node, program) {
4304
- return (node.type === AST_NODE_TYPES.CallExpression &&
4305
- getReactiveScopes(node, program).length > 0);
4306
- }
4307
- function getFixableReactiveCall(node, program) {
4308
- const [arg] = node.arguments;
4309
- if (!arg ||
4310
- arg.type === AST_NODE_TYPES.SpreadElement ||
4311
- (arg.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
4312
- arg.type !== AST_NODE_TYPES.FunctionExpression)) {
4313
- return null;
4314
- }
4315
- if (isReactiveOwnerCall(arg.body, program)) {
4316
- return arg.body;
4317
- }
4318
- if (arg.body.type !== AST_NODE_TYPES.BlockStatement || arg.body.body.length !== 1) {
4319
- return null;
4320
- }
4321
- const [statement] = arg.body.body;
4322
- if (statement?.type === AST_NODE_TYPES.ReturnStatement &&
4323
- statement.argument &&
4324
- isReactiveOwnerCall(statement.argument, program)) {
4325
- return statement.argument;
4326
- }
4327
- if (node.parent.type === AST_NODE_TYPES.ExpressionStatement &&
4328
- statement?.type === AST_NODE_TYPES.ExpressionStatement &&
4329
- isReactiveOwnerCall(statement.expression, program)) {
4330
- return statement.expression;
4331
- }
4332
- return null;
4510
+ return (isDirectCallOrNewArgument(fn) ||
4511
+ isStoredFunctionUsedAsCallOrNewArgument(fn, checker, esTreeNodeToTSNodeMap));
4333
4512
  }
4334
4513
  function isAllowedLazyAngularFactoryContext(node, program) {
4335
4514
  const fn = getEnclosingFunction(node);
4336
- if (!fn || !getFixableReactiveCall(node, program)) {
4515
+ if (!fn || !getReturnedReactiveOwnerCall(node, program)) {
4337
4516
  return false;
4338
4517
  }
4339
4518
  return (isAngularInjectionTokenFactoryFunction(fn, program) ||
@@ -4345,16 +4524,12 @@ function buildReactiveCallReplacement(outerUntrackedCall, reactiveCall, sourceCo
4345
4524
  outerUntrackedCall.parent.type !== AST_NODE_TYPES.ExpressionStatement) {
4346
4525
  return text;
4347
4526
  }
4348
- return dedent$1(text, reactiveCall.loc.start.column - outerUntrackedCall.parent.loc.start.column);
4527
+ return dedent(text, reactiveCall.loc.start.column - outerUntrackedCall.parent.loc.start.column);
4349
4528
  }
4350
- const rule$8 = createUntrackedRule({
4529
+ const rule$9 = createUntrackedRule({
4351
4530
  create(context) {
4352
- const parserServices = ESLintUtils.getParserServices(context);
4353
- const checker = parserServices.program.getTypeChecker();
4354
- const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
4355
- const { sourceCode } = context;
4356
- const program = sourceCode.ast;
4357
- const getUntrackedLocalName = () => findUntrackedAlias(program);
4531
+ const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
4532
+ const signalNodeMap = esTreeNodeToTSNodeMap;
4358
4533
  function isUntrackedUsedElsewhere(localName, excludeNode) {
4359
4534
  let found = false;
4360
4535
  walkAst(program, (node) => {
@@ -4375,18 +4550,18 @@ const rule$8 = createUntrackedRule({
4375
4550
  findEnclosingReactiveScope(node, program) ||
4376
4551
  findEnclosingReactiveScopeAfterAsyncBoundary(node, program) ||
4377
4552
  isAllowedImperativeAngularContext(node) ||
4378
- isAllowedDeferredCallbackContext(node, checker, esTreeNodeToTSNodeMap) ||
4553
+ isAllowedDeferredCallbackContext(node, checker, signalNodeMap) ||
4379
4554
  isAllowedLazyAngularFactoryContext(node, program)) {
4380
4555
  return;
4381
4556
  }
4382
- const reactiveCall = getFixableReactiveCall(node, program);
4557
+ const reactiveCall = getReturnedReactiveOwnerCall(node, program);
4383
4558
  context.report({
4384
4559
  fix: reactiveCall
4385
4560
  ? (fixer) => {
4386
4561
  const fixes = [
4387
4562
  fixer.replaceText(node, buildReactiveCallReplacement(node, reactiveCall, sourceCode)),
4388
4563
  ];
4389
- const untrackedLocalName = getUntrackedLocalName();
4564
+ const untrackedLocalName = findUntrackedAlias(program);
4390
4565
  const stillUsed = untrackedLocalName !== null &&
4391
4566
  isUntrackedUsedElsewhere(untrackedLocalName, node);
4392
4567
  if (!stillUsed) {
@@ -4418,20 +4593,16 @@ const rule$8 = createUntrackedRule({
4418
4593
  name: 'no-untracked-outside-reactive-context',
4419
4594
  });
4420
4595
 
4421
- /**
4422
- * Removes `extraSpaces` leading spaces from every line of `text` that starts
4423
- * with at least that many spaces.
4424
- */
4425
- function dedent(text, extraSpaces) {
4426
- if (extraSpaces <= 0) {
4427
- return text;
4428
- }
4429
- const prefix = ' '.repeat(extraSpaces);
4430
- return text
4431
- .split('\n')
4432
- .map((line) => (line.startsWith(prefix) ? line.slice(extraSpaces) : line))
4433
- .join('\n');
4596
+ function collectCallExpressions(root) {
4597
+ const result = [];
4598
+ walkAst(root, (node) => {
4599
+ if (node.type === AST_NODE_TYPES.CallExpression) {
4600
+ result.push(node);
4601
+ }
4602
+ });
4603
+ return result;
4434
4604
  }
4605
+
4435
4606
  /**
4436
4607
  * Builds the replacement text for the parent ExpressionStatement of an
4437
4608
  * `untracked(...)` call.
@@ -4443,13 +4614,11 @@ function dedent(text, extraSpaces) {
4443
4614
  * Returns null if the untracked argument is not a function expression.
4444
4615
  */
4445
4616
  function buildReplacement(untrackedCall, parentStatement, sourceCode) {
4446
- const [arg] = untrackedCall.arguments;
4447
- if (!arg ||
4448
- (arg.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
4449
- arg.type !== AST_NODE_TYPES.FunctionExpression)) {
4617
+ const callback = getReactiveCallbackArgument(untrackedCall);
4618
+ if (!callback) {
4450
4619
  return null;
4451
4620
  }
4452
- const { body } = arg;
4621
+ const { body } = callback;
4453
4622
  if (body.type === AST_NODE_TYPES.BlockStatement) {
4454
4623
  const { body: stmts } = body;
4455
4624
  if (stmts.length === 0) {
@@ -4464,15 +4633,6 @@ function buildReplacement(untrackedCall, parentStatement, sourceCode) {
4464
4633
  // Expression body: arrow `() => expr` — just emit `expr;`
4465
4634
  return `${sourceCode.getText(body)};`;
4466
4635
  }
4467
- function getAllCallExpressions(root) {
4468
- const result = [];
4469
- walkAst(root, (node) => {
4470
- if (node.type === AST_NODE_TYPES.CallExpression) {
4471
- result.push(node);
4472
- }
4473
- });
4474
- return result;
4475
- }
4476
4636
  function hasOpaqueSynchronousCalls(root, checker, esTreeNodeToTSNodeMap, program) {
4477
4637
  let found = false;
4478
4638
  walkSynchronousAst(root, (node) => {
@@ -4494,29 +4654,23 @@ function hasOpaqueSynchronousCalls(root, checker, esTreeNodeToTSNodeMap, program
4494
4654
  });
4495
4655
  return found;
4496
4656
  }
4497
- const rule$7 = createUntrackedRule({
4657
+ const rule$8 = createUntrackedRule({
4498
4658
  create(context) {
4499
- const parserServices = ESLintUtils.getParserServices(context);
4500
- const checker = parserServices.program.getTypeChecker();
4501
- const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
4502
- const { sourceCode } = context;
4503
- const program = sourceCode.ast;
4504
- const getUntrackedLocalName = () => getLocalNameForImport(program, '@angular/core', 'untracked');
4659
+ const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
4660
+ const signalNodeMap = esTreeNodeToTSNodeMap;
4505
4661
  function isUntrackedUsedElsewhere(localName, excludeNode) {
4506
- return getAllCallExpressions(program).some((n) => n !== excludeNode &&
4662
+ return collectCallExpressions(program).some((n) => n !== excludeNode &&
4507
4663
  n.callee.type === AST_NODE_TYPES.Identifier &&
4508
4664
  n.callee.name === localName);
4509
4665
  }
4510
4666
  function checkUntrackedCall(untrackedCall, kind) {
4511
- const [arg] = untrackedCall.arguments;
4512
- if (!arg ||
4513
- (arg.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
4514
- arg.type !== AST_NODE_TYPES.FunctionExpression)) {
4667
+ const callback = getReactiveCallbackArgument(untrackedCall);
4668
+ if (!callback) {
4515
4669
  return;
4516
4670
  }
4517
- const { reads } = collectSignalUsages(arg, checker, esTreeNodeToTSNodeMap, program);
4671
+ const { reads } = collectSignalUsages(callback, checker, signalNodeMap, program);
4518
4672
  if (reads.length > 0 ||
4519
- hasOpaqueSynchronousCalls(arg, checker, esTreeNodeToTSNodeMap, program)) {
4673
+ hasOpaqueSynchronousCalls(callback, checker, signalNodeMap, program)) {
4520
4674
  // Snapshot reads inside reactive callbacks are a valid Angular
4521
4675
  // pattern even when the snapshot later influences branching.
4522
4676
  return;
@@ -4534,7 +4688,7 @@ const rule$7 = createUntrackedRule({
4534
4688
  if (replacement === null) {
4535
4689
  return null;
4536
4690
  }
4537
- const untrackedLocalName = getUntrackedLocalName();
4691
+ const untrackedLocalName = findUntrackedAlias(program);
4538
4692
  const stillUsed = untrackedLocalName !== null &&
4539
4693
  isUntrackedUsedElsewhere(untrackedLocalName, untrackedCall);
4540
4694
  const fixes = [fixer.replaceText(parentStmt, replacement)];
@@ -4582,8 +4736,8 @@ const rule$7 = createUntrackedRule({
4582
4736
  name: 'no-useless-untracked',
4583
4737
  });
4584
4738
 
4585
- const createRule$6 = ESLintUtils.RuleCreator((name) => name);
4586
- const rule$6 = createRule$6({
4739
+ const createRule$7 = ESLintUtils.RuleCreator((name) => name);
4740
+ const rule$7 = createRule$7({
4587
4741
  create(context, [{ printWidth }]) {
4588
4742
  const sourceCode = context.sourceCode;
4589
4743
  const getLineEndIndex = (lineStartIndex) => {
@@ -4835,24 +4989,8 @@ const rule$6 = createRule$6({
4835
4989
  name: 'object-single-line',
4836
4990
  });
4837
4991
 
4838
- const createRule$5 = ESLintUtils.RuleCreator((name) => name);
4992
+ const createRule$6 = ESLintUtils.RuleCreator((name) => name);
4839
4993
  const EMPTY_ARGUMENT = '__EMPTY_ARGUMENT__';
4840
- function getParenthesizedInner(node) {
4841
- const maybeNode = node;
4842
- if (maybeNode.type === 'ParenthesizedExpression') {
4843
- return maybeNode.expression ?? null;
4844
- }
4845
- return null;
4846
- }
4847
- function unwrapParenthesized(node) {
4848
- let current = node;
4849
- let inner = getParenthesizedInner(current);
4850
- while (inner) {
4851
- current = inner;
4852
- inner = getParenthesizedInner(current);
4853
- }
4854
- return current;
4855
- }
4856
4994
  function isSupportedControlFlowStatement(node) {
4857
4995
  return (node.type === AST_NODE_TYPES.BreakStatement ||
4858
4996
  node.type === AST_NODE_TYPES.ContinueStatement ||
@@ -4920,7 +5058,7 @@ function renderTest(node, sourceCode) {
4920
5058
  const text = sourceCode.getText(node);
4921
5059
  return needsParenthesesInOrChain(node) ? `(${text})` : text;
4922
5060
  }
4923
- const rule$5 = createRule$5({
5061
+ const rule$6 = createRule$6({
4924
5062
  create(context) {
4925
5063
  const { sourceCode } = context;
4926
5064
  function checkBody(statements) {
@@ -5000,8 +5138,8 @@ const rule$5 = createRule$5({
5000
5138
 
5001
5139
  const MESSAGE_ID$1 = 'prefer-deep-imports';
5002
5140
  const ERROR_MESSAGE = 'Import via root entry point is prohibited when nested entry points exist';
5003
- const createRule$4 = ESLintUtils.RuleCreator(() => ERROR_MESSAGE);
5004
- var preferDeepImports = createRule$4({
5141
+ const createRule$5 = ESLintUtils.RuleCreator(() => ERROR_MESSAGE);
5142
+ var preferDeepImports = createRule$5({
5005
5143
  create(context, [options]) {
5006
5144
  const allowedPackages = normalizeImportFilter(options.importFilter);
5007
5145
  const isStrictMode = options.strict ?? false;
@@ -5342,7 +5480,7 @@ function buildRewrittenImports(node, baseImportPath, symbolToEntryPoint) {
5342
5480
  return importStatements.join('\n');
5343
5481
  }
5344
5482
 
5345
- const createRule$3 = ESLintUtils.RuleCreator((name) => name);
5483
+ const createRule$4 = ESLintUtils.RuleCreator((name) => name);
5346
5484
  function getPushCall(node) {
5347
5485
  if (node.expression.type !== AST_NODE_TYPES.CallExpression) {
5348
5486
  return null;
@@ -5357,7 +5495,7 @@ function getPushCall(node) {
5357
5495
  }
5358
5496
  return call;
5359
5497
  }
5360
- const rule$4 = createRule$3({
5498
+ const rule$5 = createRule$4({
5361
5499
  create(context) {
5362
5500
  const { sourceCode } = context;
5363
5501
  function checkBody(statements) {
@@ -5435,6 +5573,53 @@ const rule$4 = createRule$3({
5435
5573
  name: 'prefer-multi-arg-push',
5436
5574
  });
5437
5575
 
5576
+ const createRule$3 = ESLintUtils.RuleCreator((name) => name);
5577
+ function getModuleKeywordToken(sourceCode, node) {
5578
+ const firstToken = sourceCode.getFirstToken(node);
5579
+ if (!firstToken) {
5580
+ return null;
5581
+ }
5582
+ if (firstToken.value === 'declare') {
5583
+ return sourceCode.getTokenAfter(firstToken) ?? null;
5584
+ }
5585
+ return firstToken;
5586
+ }
5587
+ const rule$4 = createRule$3({
5588
+ create(context) {
5589
+ const { sourceCode } = context;
5590
+ return {
5591
+ TSModuleDeclaration(node) {
5592
+ if (node.kind !== 'module' ||
5593
+ node.global ||
5594
+ node.id.type === AST_NODE_TYPES.Literal) {
5595
+ return;
5596
+ }
5597
+ const moduleKeywordToken = getModuleKeywordToken(sourceCode, node);
5598
+ if (moduleKeywordToken?.value !== 'module') {
5599
+ return;
5600
+ }
5601
+ context.report({
5602
+ fix: (fixer) => fixer.replaceText(moduleKeywordToken, 'namespace'),
5603
+ messageId: 'useNamespaceKeyword',
5604
+ node: moduleKeywordToken,
5605
+ });
5606
+ },
5607
+ };
5608
+ },
5609
+ meta: {
5610
+ docs: {
5611
+ description: 'Prefer `namespace Foo {}` over the older `module Foo {}` syntax for TypeScript namespace declarations.',
5612
+ },
5613
+ fixable: 'code',
5614
+ messages: {
5615
+ useNamespaceKeyword: 'Use `namespace` instead of `module` for TypeScript namespace declarations.',
5616
+ },
5617
+ schema: [],
5618
+ type: 'problem',
5619
+ },
5620
+ name: 'prefer-namespace-keyword',
5621
+ });
5622
+
5438
5623
  /**
5439
5624
  * prefer-untracked-incidental-signal-reads
5440
5625
  *
@@ -5492,17 +5677,6 @@ function unwrapUsageExpression(node) {
5492
5677
  }
5493
5678
  return current;
5494
5679
  }
5495
- function isNodeInside(node, ancestor) {
5496
- for (let current = node; current; current = current.parent) {
5497
- if (current === ancestor) {
5498
- return true;
5499
- }
5500
- }
5501
- return false;
5502
- }
5503
- function isNodeInsideAny(node, ancestors) {
5504
- return ancestors.some((ancestor) => isNodeInside(node, ancestor));
5505
- }
5506
5680
  function isStatementPositionCall(node) {
5507
5681
  const usage = unwrapUsageExpression(node);
5508
5682
  if (usage.parent?.type === AST_NODE_TYPES.ExpressionStatement) {
@@ -5555,11 +5729,7 @@ function isAliasDeclarationIdentifier(node) {
5555
5729
  node.parent.id === node);
5556
5730
  }
5557
5731
  function aliasHasExternalUsage(alias, consumers, scope, checker, esTreeNodeToTSNodeMap) {
5558
- const tsNode = esTreeNodeToTSNodeMap.get(alias);
5559
- if (!tsNode) {
5560
- return false;
5561
- }
5562
- const symbol = checker.getSymbolAtLocation(tsNode);
5732
+ const symbol = getSymbolAtNode(alias, checker, esTreeNodeToTSNodeMap);
5563
5733
  if (!symbol) {
5564
5734
  return false;
5565
5735
  }
@@ -5571,10 +5741,7 @@ function aliasHasExternalUsage(alias, consumers, scope, checker, esTreeNodeToTSN
5571
5741
  isNodeInsideAny(node, consumers)) {
5572
5742
  return;
5573
5743
  }
5574
- const referenceTsNode = esTreeNodeToTSNodeMap.get(node);
5575
- const referenceSymbol = referenceTsNode
5576
- ? checker.getSymbolAtLocation(referenceTsNode)
5577
- : null;
5744
+ const referenceSymbol = getSymbolAtNode(node, checker, esTreeNodeToTSNodeMap);
5578
5745
  if (referenceSymbol !== symbol) {
5579
5746
  return;
5580
5747
  }
@@ -5601,11 +5768,7 @@ function resolveSignalReadAlias(expression, context, seen = new Set()) {
5601
5768
  if (unwrapped.type !== AST_NODE_TYPES.Identifier) {
5602
5769
  return null;
5603
5770
  }
5604
- const tsNode = context.esTreeNodeToTSNodeMap.get(unwrapped);
5605
- if (!tsNode) {
5606
- return null;
5607
- }
5608
- const symbol = context.checker.getSymbolAtLocation(tsNode);
5771
+ const symbol = getSymbolAtNode(unwrapped, context.checker, context.esTreeNodeToTSNodeMap);
5609
5772
  if (!symbol) {
5610
5773
  return null;
5611
5774
  }
@@ -5693,12 +5856,9 @@ function collectSuspiciousReads(scope, checker, esTreeNodeToTSNodeMap, tsNodeToE
5693
5856
  }
5694
5857
  const rule$3 = createUntrackedRule({
5695
5858
  create(context) {
5696
- const parserServices = ESLintUtils.getParserServices(context);
5697
- const checker = parserServices.program.getTypeChecker();
5698
- const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
5699
- const tsNodeToESTreeNodeMap = parserServices.tsNodeToESTreeNodeMap;
5700
- const { sourceCode } = context;
5701
- const program = sourceCode.ast;
5859
+ const { checker, esTreeNodeToTSNodeMap, program, sourceCode, tsNodeToESTreeNodeMap, } = getTypeAwareRuleContext(context);
5860
+ const signalNodeMap = esTreeNodeToTSNodeMap;
5861
+ const estreeNodeMap = tsNodeToESTreeNodeMap;
5702
5862
  function buildFix(read) {
5703
5863
  const untrackedAlias = findUntrackedAlias(program);
5704
5864
  const alreadyHasUntracked = untrackedAlias !== null;
@@ -5714,13 +5874,13 @@ const rule$3 = createUntrackedRule({
5714
5874
  return {
5715
5875
  CallExpression(node) {
5716
5876
  for (const scope of getReactiveScopes(node, program)) {
5717
- const suspicious = collectSuspiciousReads(scope, checker, esTreeNodeToTSNodeMap, tsNodeToESTreeNodeMap, program);
5718
- const { reads: trackedReads } = collectSignalUsages(scope.callback, checker, esTreeNodeToTSNodeMap, program);
5877
+ const suspicious = collectSuspiciousReads(scope, checker, signalNodeMap, estreeNodeMap, program);
5878
+ const { reads: trackedReads } = collectSignalUsages(scope.callback, checker, signalNodeMap, program);
5719
5879
  const suspiciousReads = new Set(suspicious.map(({ read }) => read));
5720
5880
  for (const { aliases, consumers, read } of suspicious) {
5721
5881
  const hasTrackedDependency = consumers.some((consumer) => trackedReads.some((trackedRead) => !suspiciousReads.has(trackedRead) &&
5722
5882
  !isNodeInside(trackedRead, consumer)));
5723
- const hasExternalAliasUsage = aliases.some((alias) => aliasHasExternalUsage(alias, consumers, scope, checker, esTreeNodeToTSNodeMap));
5883
+ const hasExternalAliasUsage = aliases.some((alias) => aliasHasExternalUsage(alias, consumers, scope, checker, signalNodeMap));
5724
5884
  if (!hasTrackedDependency || hasExternalAliasUsage) {
5725
5885
  continue;
5726
5886
  }
@@ -5752,7 +5912,7 @@ const rule$3 = createUntrackedRule({
5752
5912
 
5753
5913
  function getReturnedExpression(node) {
5754
5914
  if (node.body.type !== AST_NODE_TYPES.BlockStatement) {
5755
- return unwrapExpression(node.body);
5915
+ return node.body;
5756
5916
  }
5757
5917
  if (node.body.body.length !== 1) {
5758
5918
  return null;
@@ -5761,17 +5921,16 @@ function getReturnedExpression(node) {
5761
5921
  if (statement?.type !== AST_NODE_TYPES.ReturnStatement || !statement.argument) {
5762
5922
  return null;
5763
5923
  }
5764
- return unwrapExpression(statement.argument);
5924
+ return statement.argument;
5765
5925
  }
5926
+
5766
5927
  function getWrappedSignalGetter(node, checker, esTreeNodeToTSNodeMap) {
5767
- const [arg] = node.arguments;
5768
- if (!arg ||
5769
- arg.type === AST_NODE_TYPES.SpreadElement ||
5770
- (arg.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
5771
- arg.type !== AST_NODE_TYPES.FunctionExpression)) {
5928
+ const callback = getReactiveCallbackArgument(node);
5929
+ if (!callback) {
5772
5930
  return null;
5773
5931
  }
5774
- const body = getReturnedExpression(arg);
5932
+ const returnedExpression = getReturnedExpression(callback);
5933
+ const body = returnedExpression ? unwrapExpression(returnedExpression) : null;
5775
5934
  if (body?.type !== AST_NODE_TYPES.CallExpression ||
5776
5935
  !isSignalReadCall(body, checker, esTreeNodeToTSNodeMap)) {
5777
5936
  return null;
@@ -5785,17 +5944,14 @@ function getWrappedSignalGetter(node, checker, esTreeNodeToTSNodeMap) {
5785
5944
  }
5786
5945
  const rule$2 = createUntrackedRule({
5787
5946
  create(context) {
5788
- const parserServices = ESLintUtils.getParserServices(context);
5789
- const checker = parserServices.program.getTypeChecker();
5790
- const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap;
5791
- const { sourceCode } = context;
5792
- const program = sourceCode.ast;
5947
+ const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
5948
+ const signalNodeMap = esTreeNodeToTSNodeMap;
5793
5949
  return {
5794
5950
  CallExpression(node) {
5795
5951
  if (!isAngularUntrackedCall(node, program)) {
5796
5952
  return;
5797
5953
  }
5798
- const getter = getWrappedSignalGetter(node, checker, esTreeNodeToTSNodeMap);
5954
+ const getter = getWrappedSignalGetter(node, checker, signalNodeMap);
5799
5955
  if (!getter) {
5800
5956
  return;
5801
5957
  }
@@ -5822,13 +5978,6 @@ const rule$2 = createUntrackedRule({
5822
5978
  name: 'prefer-untracked-signal-getter',
5823
5979
  });
5824
5980
 
5825
- function getImportedName(spec) {
5826
- if (spec.imported.type === AST_NODE_TYPES.Identifier) {
5827
- return spec.imported.name;
5828
- }
5829
- return spec.imported.value;
5830
- }
5831
-
5832
5981
  function isImportsArrayProperty(property) {
5833
5982
  const isProperty = property?.type === AST_NODE_TYPES.Property;
5834
5983
  const hasIdentifierKey = property?.key.type === AST_NODE_TYPES.Identifier &&
@@ -5836,6 +5985,13 @@ function isImportsArrayProperty(property) {
5836
5985
  return isProperty && hasIdentifierKey && isArray(property.value);
5837
5986
  }
5838
5987
 
5988
+ function getImportedName(spec) {
5989
+ if (spec.imported.type === AST_NODE_TYPES.Identifier) {
5990
+ return spec.imported.name;
5991
+ }
5992
+ return spec.imported.value;
5993
+ }
5994
+
5839
5995
  const MESSAGE_ID = 'replaceTuiImport';
5840
5996
  const DEFAULT_DECORATORS = ['Component', 'Directive', 'NgModule', 'Pipe'];
5841
5997
  const DEFAULT_EXCEPTIONS = [
@@ -6246,27 +6402,31 @@ const plugin = {
6246
6402
  'class-property-naming': classPropertyNaming,
6247
6403
  'decorator-key-sort': config$3,
6248
6404
  'flat-exports': flatExports,
6249
- 'host-attributes-sort': rule$j,
6405
+ 'host-attributes-sort': rule$n,
6250
6406
  'html-logical-properties': config$2,
6251
- 'injection-token-description': rule$i,
6252
- 'no-deep-imports': rule$h,
6407
+ 'injection-token-description': rule$m,
6408
+ 'no-commonjs-import-patterns': rule$l,
6409
+ 'no-deep-imports': rule$k,
6253
6410
  'no-deep-imports-to-indexed-packages': noDeepImportsToIndexedPackages,
6254
- 'no-fully-untracked-effect': rule$g,
6411
+ 'no-fully-untracked-effect': rule$j,
6255
6412
  'no-href-with-router-link': config$1,
6256
- 'no-implicit-public': rule$f,
6257
- 'no-legacy-peer-deps': rule$e,
6258
- 'no-playwright-empty-fill': rule$d,
6413
+ 'no-implicit-public': rule$i,
6414
+ 'no-import-assertions': rule$h,
6415
+ 'no-infinite-loop': rule$g,
6416
+ 'no-legacy-peer-deps': rule$f,
6417
+ 'no-playwright-empty-fill': rule$e,
6259
6418
  'no-project-as-in-ng-template': config,
6260
- 'no-redundant-type-annotation': rule$c,
6261
- 'no-side-effects-in-computed': rule$b,
6262
- 'no-signal-reads-after-await-in-reactive-context': rule$a,
6263
- 'no-string-literal-concat': rule$9,
6264
- 'no-untracked-outside-reactive-context': rule$8,
6265
- 'no-useless-untracked': rule$7,
6266
- 'object-single-line': rule$6,
6267
- 'prefer-combined-if-control-flow': rule$5,
6419
+ 'no-redundant-type-annotation': rule$d,
6420
+ 'no-side-effects-in-computed': rule$c,
6421
+ 'no-signal-reads-after-await-in-reactive-context': rule$b,
6422
+ 'no-string-literal-concat': rule$a,
6423
+ 'no-untracked-outside-reactive-context': rule$9,
6424
+ 'no-useless-untracked': rule$8,
6425
+ 'object-single-line': rule$7,
6426
+ 'prefer-combined-if-control-flow': rule$6,
6268
6427
  'prefer-deep-imports': preferDeepImports,
6269
- 'prefer-multi-arg-push': rule$4,
6428
+ 'prefer-multi-arg-push': rule$5,
6429
+ 'prefer-namespace-keyword': rule$4,
6270
6430
  'prefer-untracked-incidental-signal-reads': rule$3,
6271
6431
  'prefer-untracked-signal-getter': rule$2,
6272
6432
  'short-tui-imports': rule$1,