@taiga-ui/eslint-plugin-experience-next 0.505.0 → 0.506.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.
- package/README.md +1 -0
- package/index.d.ts +3 -0
- package/index.esm.js +188 -82
- package/package.json +1 -1
- package/rules/recommended/prefer-loose-null-check.d.ts +4 -0
package/README.md
CHANGED
|
@@ -109,6 +109,7 @@ from third-party plugins. The exact severities and file globs live in
|
|
|
109
109
|
| [object-single-line](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/object-single-line.md) | Enforce single-line formatting for single-property objects when it fits `printWidth` | ✅ | 🔧 | |
|
|
110
110
|
| [prefer-combined-if-control-flow](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-combined-if-control-flow.md) | Combine consecutive `if` statements that use the same `return`, `break`, `continue`, or `throw` | ✅ | 🔧 | |
|
|
111
111
|
| [prefer-deep-imports](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-deep-imports.md) | Allow deep imports of Taiga UI packages | | 🔧 | |
|
|
112
|
+
| [prefer-loose-null-check](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-loose-null-check.md) | Prefer loose null checks over paired strict comparisons against `null` and `undefined` | ✅ | 🔧 | |
|
|
112
113
|
| [prefer-multi-arg-push](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-multi-arg-push.md) | Combine consecutive `.push()` calls on the same array into a single multi-argument call | ✅ | 🔧 | |
|
|
113
114
|
| [prefer-namespace-keyword](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-namespace-keyword.md) | Replace `module Foo {}` with `namespace Foo {}` for TypeScript namespace declarations | ✅ | 🔧 | |
|
|
114
115
|
| [prefer-untracked-incidental-signal-reads](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-untracked-incidental-signal-reads.md) | Wrap likely-incidental signal reads with `untracked()` in reactive callbacks | ✅ | 🔧 | |
|
package/index.d.ts
CHANGED
|
@@ -148,6 +148,9 @@ declare const plugin: {
|
|
|
148
148
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
149
149
|
name: string;
|
|
150
150
|
};
|
|
151
|
+
'prefer-loose-null-check': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferLooseNullCheck", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
152
|
+
name: string;
|
|
153
|
+
};
|
|
151
154
|
'prefer-multi-arg-push': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferMultiArgPush", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
152
155
|
name: string;
|
|
153
156
|
};
|
package/index.esm.js
CHANGED
|
@@ -1213,6 +1213,7 @@ var recommended = defineConfig([
|
|
|
1213
1213
|
'@taiga-ui/experience-next/no-useless-untracked': 'error',
|
|
1214
1214
|
'@taiga-ui/experience-next/object-single-line': ['error', { printWidth: 90 }],
|
|
1215
1215
|
'@taiga-ui/experience-next/prefer-combined-if-control-flow': 'error',
|
|
1216
|
+
'@taiga-ui/experience-next/prefer-loose-null-check': 'error',
|
|
1216
1217
|
'@taiga-ui/experience-next/prefer-multi-arg-push': 'error',
|
|
1217
1218
|
'@taiga-ui/experience-next/prefer-namespace-keyword': 'error',
|
|
1218
1219
|
'@taiga-ui/experience-next/prefer-untracked-incidental-signal-reads': 'error',
|
|
@@ -46223,7 +46224,7 @@ function buildMultilineStartTag(node, sourceText) {
|
|
|
46223
46224
|
closing,
|
|
46224
46225
|
].join('\n');
|
|
46225
46226
|
}
|
|
46226
|
-
const rule$
|
|
46227
|
+
const rule$Q = createRule({
|
|
46227
46228
|
name: 'attrs-newline',
|
|
46228
46229
|
rule: {
|
|
46229
46230
|
create(context) {
|
|
@@ -46370,7 +46371,7 @@ const config$5 = {
|
|
|
46370
46371
|
function getCorrectOrderRelative(correct, current) {
|
|
46371
46372
|
return correct.filter((item) => current.includes(item));
|
|
46372
46373
|
}
|
|
46373
|
-
const rule$
|
|
46374
|
+
const rule$P = createRule({
|
|
46374
46375
|
name: 'decorator-key-sort',
|
|
46375
46376
|
rule: config$5,
|
|
46376
46377
|
});
|
|
@@ -46434,7 +46435,7 @@ function getNodeLabel(node) {
|
|
|
46434
46435
|
}
|
|
46435
46436
|
return 'text';
|
|
46436
46437
|
}
|
|
46437
|
-
const rule$
|
|
46438
|
+
const rule$O = createRule({
|
|
46438
46439
|
name: 'element-newline',
|
|
46439
46440
|
rule: {
|
|
46440
46441
|
create(context) {
|
|
@@ -46665,7 +46666,7 @@ const PRESETS = {
|
|
|
46665
46666
|
$VUE: ['$CLASS', '$ID', '$VUE_ATTRIBUTE'],
|
|
46666
46667
|
$VUE_ATTRIBUTE: /^v-/,
|
|
46667
46668
|
};
|
|
46668
|
-
const rule$
|
|
46669
|
+
const rule$N = createRule({
|
|
46669
46670
|
create(context, [options]) {
|
|
46670
46671
|
const sourceCode = context.sourceCode;
|
|
46671
46672
|
const settings = {
|
|
@@ -46779,7 +46780,7 @@ function getHostAttributeProperties(hostObject) {
|
|
|
46779
46780
|
return null;
|
|
46780
46781
|
}
|
|
46781
46782
|
const name = getStaticPropertyName(property.key);
|
|
46782
|
-
if (name
|
|
46783
|
+
if (name == null) {
|
|
46783
46784
|
return null;
|
|
46784
46785
|
}
|
|
46785
46786
|
properties.push({ name, node: property });
|
|
@@ -46998,7 +46999,7 @@ const config$4 = {
|
|
|
46998
46999
|
type: 'suggestion',
|
|
46999
47000
|
},
|
|
47000
47001
|
};
|
|
47001
|
-
const rule$
|
|
47002
|
+
const rule$M = createRule({
|
|
47002
47003
|
name: 'html-logical-properties',
|
|
47003
47004
|
rule: config$4,
|
|
47004
47005
|
});
|
|
@@ -248250,7 +248251,7 @@ function isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode) {
|
|
|
248250
248251
|
}
|
|
248251
248252
|
return hasSafeRuntimeUsage;
|
|
248252
248253
|
}
|
|
248253
|
-
const rule$
|
|
248254
|
+
const rule$L = createRule({
|
|
248254
248255
|
create(context) {
|
|
248255
248256
|
const { checker, esTreeNodeToTSNodeMap, sourceCode, tsProgram } = getTypeAwareRuleContext(context);
|
|
248256
248257
|
const checkCycles = context.options[0]?.checkCycles ?? true;
|
|
@@ -248956,7 +248957,7 @@ function prependTokenName(text, name) {
|
|
|
248956
248957
|
return `${text.slice(0, 1)}[${name}]: ${text.slice(1)}`;
|
|
248957
248958
|
}
|
|
248958
248959
|
function isNgDevModeVisible(sourceCode, node) {
|
|
248959
|
-
for (let scope = sourceCode.getScope(node); scope
|
|
248960
|
+
for (let scope = sourceCode.getScope(node); scope != null; scope = scope.upper) {
|
|
248960
248961
|
if (scope.variables.some((variable) => variable.name === NG_DEV_MODE)) {
|
|
248961
248962
|
return true;
|
|
248962
248963
|
}
|
|
@@ -248976,7 +248977,7 @@ function getNgDevModeDeclarationFix(program, fixer) {
|
|
|
248976
248977
|
}
|
|
248977
248978
|
return fixer.insertTextBeforeRange([0, 0], 'declare const ngDevMode: boolean;\n');
|
|
248978
248979
|
}
|
|
248979
|
-
const rule$
|
|
248980
|
+
const rule$K = createRule({
|
|
248980
248981
|
create(context) {
|
|
248981
248982
|
const { sourceCode } = context;
|
|
248982
248983
|
const program = sourceCode.ast;
|
|
@@ -249025,7 +249026,7 @@ const rule$J = createRule({
|
|
|
249025
249026
|
name: 'injection-token-description',
|
|
249026
249027
|
});
|
|
249027
249028
|
|
|
249028
|
-
const rule$
|
|
249029
|
+
const rule$J = createRule({
|
|
249029
249030
|
create(context) {
|
|
249030
249031
|
const { sourceCode } = context;
|
|
249031
249032
|
const namespaceImports = new Map();
|
|
@@ -249120,7 +249121,7 @@ const DEFAULT_OPTIONS = {
|
|
|
249120
249121
|
importDeclaration: '^@taiga-ui*',
|
|
249121
249122
|
projectName: String.raw `(?<=^@taiga-ui/)([-\w]+)`,
|
|
249122
249123
|
};
|
|
249123
|
-
const rule$
|
|
249124
|
+
const rule$I = createRule({
|
|
249124
249125
|
create(context) {
|
|
249125
249126
|
const { currentProject, deepImport, ignoreImports, importDeclaration, projectName, } = { ...DEFAULT_OPTIONS, ...context.options[0] };
|
|
249126
249127
|
const hasNonCodeExtension = (source) => {
|
|
@@ -249212,7 +249213,7 @@ const nearestFileUpCache = new Map();
|
|
|
249212
249213
|
const markerCache = new Map();
|
|
249213
249214
|
const indexFileCache = new Map();
|
|
249214
249215
|
const indexExportsCache = new Map();
|
|
249215
|
-
const rule$
|
|
249216
|
+
const rule$H = createRule({
|
|
249216
249217
|
create(context) {
|
|
249217
249218
|
const parserServices = dist$3.ESLintUtils.getParserServices(context);
|
|
249218
249219
|
const program = parserServices.program;
|
|
@@ -249227,7 +249228,7 @@ const rule$G = createRule({
|
|
|
249227
249228
|
}
|
|
249228
249229
|
const key = `${containingDir}\0${moduleSpecifier}`;
|
|
249229
249230
|
const cachedFile = cache.get(key);
|
|
249230
|
-
if (cachedFile
|
|
249231
|
+
if (cachedFile != null) {
|
|
249231
249232
|
return cachedFile;
|
|
249232
249233
|
}
|
|
249233
249234
|
const resolved = ts.resolveModuleName(moduleSpecifier, context.filename, compilerOptions, compilerHost);
|
|
@@ -249238,7 +249239,7 @@ const rule$G = createRule({
|
|
|
249238
249239
|
function findNearestFileUpwardsCached(startDirectory, fileName) {
|
|
249239
249240
|
const key = `${startDirectory}\0${fileName}`;
|
|
249240
249241
|
const cachedPath = nearestFileUpCache.get(key);
|
|
249241
|
-
if (cachedPath
|
|
249242
|
+
if (cachedPath != null) {
|
|
249242
249243
|
return cachedPath;
|
|
249243
249244
|
}
|
|
249244
249245
|
let currentDirectory = startDirectory;
|
|
@@ -249259,7 +249260,7 @@ const rule$G = createRule({
|
|
|
249259
249260
|
}
|
|
249260
249261
|
function pickPackageMarkerFileCached(resolvedRootFilePath) {
|
|
249261
249262
|
const cachedMarker = markerCache.get(resolvedRootFilePath);
|
|
249262
|
-
if (cachedMarker
|
|
249263
|
+
if (cachedMarker != null) {
|
|
249263
249264
|
return cachedMarker;
|
|
249264
249265
|
}
|
|
249265
249266
|
const resolvedRootDirectory = path.dirname(resolvedRootFilePath);
|
|
@@ -249271,7 +249272,7 @@ const rule$G = createRule({
|
|
|
249271
249272
|
}
|
|
249272
249273
|
function pickIndexFileInDirectoryCached(packageDirectory) {
|
|
249273
249274
|
const cachedIndexFile = indexFileCache.get(packageDirectory);
|
|
249274
|
-
if (cachedIndexFile
|
|
249275
|
+
if (cachedIndexFile != null) {
|
|
249275
249276
|
return cachedIndexFile;
|
|
249276
249277
|
}
|
|
249277
249278
|
const indexTypescriptPath = path.join(packageDirectory, 'index.ts');
|
|
@@ -249409,13 +249410,13 @@ const noDuplicateAttributesRule = angular.templatePlugin.rules?.['no-duplicate-a
|
|
|
249409
249410
|
if (!noDuplicateAttributesRule) {
|
|
249410
249411
|
throw new Error('angular-eslint template rule "no-duplicate-attributes" is not available');
|
|
249411
249412
|
}
|
|
249412
|
-
const rule$
|
|
249413
|
+
const rule$G = createRule({
|
|
249413
249414
|
name: 'no-duplicate-attrs',
|
|
249414
249415
|
rule: noDuplicateAttributesRule,
|
|
249415
249416
|
});
|
|
249416
249417
|
|
|
249417
249418
|
const MESSAGE_ID$c = 'duplicateId';
|
|
249418
|
-
const rule$
|
|
249419
|
+
const rule$F = createRule({
|
|
249419
249420
|
name: 'no-duplicate-id',
|
|
249420
249421
|
rule: {
|
|
249421
249422
|
create(context) {
|
|
@@ -249477,7 +249478,7 @@ function getTrackingKey(node) {
|
|
|
249477
249478
|
}
|
|
249478
249479
|
return null;
|
|
249479
249480
|
}
|
|
249480
|
-
const rule$
|
|
249481
|
+
const rule$E = createRule({
|
|
249481
249482
|
name: 'no-duplicate-in-head',
|
|
249482
249483
|
rule: {
|
|
249483
249484
|
create(context) {
|
|
@@ -249543,7 +249544,7 @@ function getOrderedChildren(node) {
|
|
|
249543
249544
|
...node.params,
|
|
249544
249545
|
node.body,
|
|
249545
249546
|
];
|
|
249546
|
-
return children.filter((child) => child
|
|
249547
|
+
return children.filter((child) => child != null);
|
|
249547
249548
|
}
|
|
249548
249549
|
if (node.type === dist$3.AST_NODE_TYPES.BlockStatement ||
|
|
249549
249550
|
node.type === dist$3.AST_NODE_TYPES.Program) {
|
|
@@ -249570,7 +249571,7 @@ function getOrderedChildren(node) {
|
|
|
249570
249571
|
node.update,
|
|
249571
249572
|
node.body,
|
|
249572
249573
|
];
|
|
249573
|
-
return children.filter((child) => child
|
|
249574
|
+
return children.filter((child) => child != null);
|
|
249574
249575
|
}
|
|
249575
249576
|
if (node.type === dist$3.AST_NODE_TYPES.ForInStatement ||
|
|
249576
249577
|
node.type === dist$3.AST_NODE_TYPES.ForOfStatement) {
|
|
@@ -250062,7 +250063,7 @@ const ANGULAR_SIGNALS_UNTRACKED_GUIDE_URL = 'https://angular.dev/guide/signals#r
|
|
|
250062
250063
|
const ANGULAR_SIGNALS_ASYNC_GUIDE_URL = 'https://angular.dev/guide/signals#reactive-context-and-async-operations';
|
|
250063
250064
|
const createUntrackedRule = createRule;
|
|
250064
250065
|
|
|
250065
|
-
const rule$
|
|
250066
|
+
const rule$D = createUntrackedRule({
|
|
250066
250067
|
create(context) {
|
|
250067
250068
|
const { checker, esTreeNodeToTSNodeMap, program } = getTypeAwareRuleContext(context);
|
|
250068
250069
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -250135,7 +250136,7 @@ const config$3 = {
|
|
|
250135
250136
|
type: 'problem',
|
|
250136
250137
|
},
|
|
250137
250138
|
};
|
|
250138
|
-
const rule$
|
|
250139
|
+
const rule$C = createRule({
|
|
250139
250140
|
name: 'no-href-with-router-link',
|
|
250140
250141
|
rule: config$3,
|
|
250141
250142
|
});
|
|
@@ -250196,7 +250197,7 @@ function getScopeRoot(node) {
|
|
|
250196
250197
|
return (findAncestor(node, (ancestor) => ancestor.type === dist$3.AST_NODE_TYPES.Program || isFunctionLike(ancestor)) ?? node);
|
|
250197
250198
|
}
|
|
250198
250199
|
|
|
250199
|
-
const rule$
|
|
250200
|
+
const rule$B = createRule({
|
|
250200
250201
|
create(context) {
|
|
250201
250202
|
const checkImplicitPublic = (node) => {
|
|
250202
250203
|
const classRef = getEnclosingClass(node);
|
|
@@ -250258,7 +250259,7 @@ const rule$A = createRule({
|
|
|
250258
250259
|
name: 'no-implicit-public',
|
|
250259
250260
|
});
|
|
250260
250261
|
|
|
250261
|
-
const rule$
|
|
250262
|
+
const rule$A = createRule({
|
|
250262
250263
|
create(context) {
|
|
250263
250264
|
const { sourceCode } = context;
|
|
250264
250265
|
return {
|
|
@@ -250314,9 +250315,9 @@ function isInfiniteLoopLiteral(node) {
|
|
|
250314
250315
|
return unwrapped.value === true || unwrapped.value === 1;
|
|
250315
250316
|
}
|
|
250316
250317
|
function isInfiniteLoopTest(test) {
|
|
250317
|
-
return test
|
|
250318
|
+
return test == null || isInfiniteLoopLiteral(test);
|
|
250318
250319
|
}
|
|
250319
|
-
const rule$
|
|
250320
|
+
const rule$z = createRule({
|
|
250320
250321
|
create(context) {
|
|
250321
250322
|
return {
|
|
250322
250323
|
DoWhileStatement(node) {
|
|
@@ -250361,7 +250362,7 @@ const rule$y = createRule({
|
|
|
250361
250362
|
});
|
|
250362
250363
|
|
|
250363
250364
|
const LEGACY_PEER_DEPS_PATTERN = /^legacy-peer-deps\s*=\s*true$/i;
|
|
250364
|
-
const rule$
|
|
250365
|
+
const rule$y = createRule({
|
|
250365
250366
|
create(context) {
|
|
250366
250367
|
return {
|
|
250367
250368
|
Program(node) {
|
|
@@ -250821,7 +250822,7 @@ const OBSOLETE_HTML_ATTRS = {
|
|
|
250821
250822
|
};
|
|
250822
250823
|
|
|
250823
250824
|
const MESSAGE_ID$9 = 'obsolete';
|
|
250824
|
-
const rule$
|
|
250825
|
+
const rule$x = createRule({
|
|
250825
250826
|
name: 'no-obsolete-attrs',
|
|
250826
250827
|
rule: {
|
|
250827
250828
|
create(context) {
|
|
@@ -250899,7 +250900,7 @@ const OBSOLETE_HTML_TAGS = new Set([
|
|
|
250899
250900
|
]);
|
|
250900
250901
|
|
|
250901
250902
|
const MESSAGE_ID$8 = 'unexpected';
|
|
250902
|
-
const rule$
|
|
250903
|
+
const rule$w = createRule({
|
|
250903
250904
|
name: 'no-obsolete-tags',
|
|
250904
250905
|
rule: {
|
|
250905
250906
|
create(context) {
|
|
@@ -250926,7 +250927,7 @@ const rule$v = createRule({
|
|
|
250926
250927
|
},
|
|
250927
250928
|
});
|
|
250928
250929
|
|
|
250929
|
-
const rule$
|
|
250930
|
+
const rule$v = createRule({
|
|
250930
250931
|
create(context) {
|
|
250931
250932
|
const { checker, esTreeNodeToTSNodeMap, sourceCode } = getTypeAwareRuleContext(context);
|
|
250932
250933
|
return {
|
|
@@ -251070,7 +251071,7 @@ const config$2 = {
|
|
|
251070
251071
|
type: 'problem',
|
|
251071
251072
|
},
|
|
251072
251073
|
};
|
|
251073
|
-
const rule$
|
|
251074
|
+
const rule$u = createRule({
|
|
251074
251075
|
name: 'no-project-as-in-ng-template',
|
|
251075
251076
|
rule: config$2,
|
|
251076
251077
|
});
|
|
@@ -251107,7 +251108,7 @@ function collectArrayExpressions(node) {
|
|
|
251107
251108
|
}
|
|
251108
251109
|
return result;
|
|
251109
251110
|
}
|
|
251110
|
-
const rule$
|
|
251111
|
+
const rule$t = createRule({
|
|
251111
251112
|
create(context) {
|
|
251112
251113
|
const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
|
|
251113
251114
|
const ignoreTupleContextualTyping = context.options[0]?.ignoreTupleContextualTyping ?? true;
|
|
@@ -251282,7 +251283,7 @@ function getStatementIndent(statement, sourceText) {
|
|
|
251282
251283
|
const before = sourceText.slice(lineStart, start);
|
|
251283
251284
|
return /^\s*$/.test(before) ? before : '';
|
|
251284
251285
|
}
|
|
251285
|
-
const rule$
|
|
251286
|
+
const rule$s = createRule({
|
|
251286
251287
|
create(context) {
|
|
251287
251288
|
const { checker, esTreeNodeToTSNodeMap, sourceCode } = getTypeAwareRuleContext(context);
|
|
251288
251289
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -251713,7 +251714,7 @@ function inspectComputedBody(root, context, localScopes, visitedFunctions, repor
|
|
|
251713
251714
|
return;
|
|
251714
251715
|
});
|
|
251715
251716
|
}
|
|
251716
|
-
const rule$
|
|
251717
|
+
const rule$r = createRule({
|
|
251717
251718
|
create(context) {
|
|
251718
251719
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode, tsNodeToESTreeNodeMap, } = getTypeAwareRuleContext(context);
|
|
251719
251720
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -251756,7 +251757,7 @@ const rule$q = createRule({
|
|
|
251756
251757
|
name: 'no-side-effects-in-computed',
|
|
251757
251758
|
});
|
|
251758
251759
|
|
|
251759
|
-
const rule$
|
|
251760
|
+
const rule$q = createUntrackedRule({
|
|
251760
251761
|
create(context) {
|
|
251761
251762
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
251762
251763
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -251850,7 +251851,7 @@ function templateContent(template, renderExpr) {
|
|
|
251850
251851
|
: ''}`)
|
|
251851
251852
|
.join('');
|
|
251852
251853
|
}
|
|
251853
|
-
const rule$
|
|
251854
|
+
const rule$p = createRule({
|
|
251854
251855
|
create(context) {
|
|
251855
251856
|
const { sourceCode } = context;
|
|
251856
251857
|
let parserServices = null;
|
|
@@ -252185,7 +252186,7 @@ function buildReactiveCallReplacement(outerUntrackedCall, reactiveCall, sourceCo
|
|
|
252185
252186
|
}
|
|
252186
252187
|
return dedent(text, reactiveCall.loc.start.column - outerUntrackedCall.parent.loc.start.column);
|
|
252187
252188
|
}
|
|
252188
|
-
const rule$
|
|
252189
|
+
const rule$o = createUntrackedRule({
|
|
252189
252190
|
create(context) {
|
|
252190
252191
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
252191
252192
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -252221,7 +252222,7 @@ const rule$n = createUntrackedRule({
|
|
|
252221
252222
|
fixer.replaceText(node, buildReactiveCallReplacement(node, reactiveCall, sourceCode)),
|
|
252222
252223
|
];
|
|
252223
252224
|
const untrackedLocalName = findUntrackedAlias(program);
|
|
252224
|
-
const stillUsed = untrackedLocalName
|
|
252225
|
+
const stillUsed = untrackedLocalName != null &&
|
|
252225
252226
|
isUntrackedUsedElsewhere(untrackedLocalName, node);
|
|
252226
252227
|
if (!stillUsed) {
|
|
252227
252228
|
fixes.push(...buildImportRemovalFixes(program, fixer, sourceCode));
|
|
@@ -252314,7 +252315,7 @@ function hasOpaqueSynchronousCalls(root, checker, esTreeNodeToTSNodeMap, program
|
|
|
252314
252315
|
});
|
|
252315
252316
|
return found;
|
|
252316
252317
|
}
|
|
252317
|
-
const rule$
|
|
252318
|
+
const rule$n = createUntrackedRule({
|
|
252318
252319
|
create(context) {
|
|
252319
252320
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
252320
252321
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -252345,11 +252346,11 @@ const rule$m = createUntrackedRule({
|
|
|
252345
252346
|
? (fixer) => {
|
|
252346
252347
|
const parentStmt = parent;
|
|
252347
252348
|
const replacement = buildReplacement(untrackedCall, parentStmt, sourceCode);
|
|
252348
|
-
if (replacement
|
|
252349
|
+
if (replacement == null) {
|
|
252349
252350
|
return null;
|
|
252350
252351
|
}
|
|
252351
252352
|
const untrackedLocalName = findUntrackedAlias(program);
|
|
252352
|
-
const stillUsed = untrackedLocalName
|
|
252353
|
+
const stillUsed = untrackedLocalName != null &&
|
|
252353
252354
|
isUntrackedUsedElsewhere(untrackedLocalName, untrackedCall);
|
|
252354
252355
|
const fixes = [fixer.replaceText(parentStmt, replacement)];
|
|
252355
252356
|
if (!stillUsed) {
|
|
@@ -252396,7 +252397,7 @@ const rule$m = createUntrackedRule({
|
|
|
252396
252397
|
name: 'no-useless-untracked',
|
|
252397
252398
|
});
|
|
252398
252399
|
|
|
252399
|
-
const rule$
|
|
252400
|
+
const rule$m = createRule({
|
|
252400
252401
|
create(context, [{ printWidth }]) {
|
|
252401
252402
|
const sourceCode = context.sourceCode;
|
|
252402
252403
|
const getLineEndIndex = (lineStartIndex) => {
|
|
@@ -252717,7 +252718,7 @@ function renderTest(node, sourceCode) {
|
|
|
252717
252718
|
const text = sourceCode.getText(node);
|
|
252718
252719
|
return needsParenthesesInOrChain(node) ? `(${text})` : text;
|
|
252719
252720
|
}
|
|
252720
|
-
const rule$
|
|
252721
|
+
const rule$l = createRule({
|
|
252721
252722
|
create(context) {
|
|
252722
252723
|
const { sourceCode } = context;
|
|
252723
252724
|
function checkBody(statements) {
|
|
@@ -252806,6 +252807,110 @@ const rule$k = createRule({
|
|
|
252806
252807
|
name: 'prefer-combined-if-control-flow',
|
|
252807
252808
|
});
|
|
252808
252809
|
|
|
252810
|
+
function parseStrictNullCheck(node, getText) {
|
|
252811
|
+
if (node.type !== dist$3.AST_NODE_TYPES.BinaryExpression) {
|
|
252812
|
+
return null;
|
|
252813
|
+
}
|
|
252814
|
+
const { left, operator, right } = node;
|
|
252815
|
+
if (operator !== '!==' && operator !== '===') {
|
|
252816
|
+
return null;
|
|
252817
|
+
}
|
|
252818
|
+
if (right.type === dist$3.AST_NODE_TYPES.Literal && right.value === null) {
|
|
252819
|
+
return { comparedWith: 'null', operand: getText(left), strictOp: operator };
|
|
252820
|
+
}
|
|
252821
|
+
if (right.type === dist$3.AST_NODE_TYPES.Identifier && right.name === 'undefined') {
|
|
252822
|
+
return { comparedWith: 'undefined', operand: getText(left), strictOp: operator };
|
|
252823
|
+
}
|
|
252824
|
+
if (left.type === dist$3.AST_NODE_TYPES.Literal && left.value === null) {
|
|
252825
|
+
return { comparedWith: 'null', operand: getText(right), strictOp: operator };
|
|
252826
|
+
}
|
|
252827
|
+
if (left.type === dist$3.AST_NODE_TYPES.Identifier && left.name === 'undefined') {
|
|
252828
|
+
return { comparedWith: 'undefined', operand: getText(right), strictOp: operator };
|
|
252829
|
+
}
|
|
252830
|
+
return null;
|
|
252831
|
+
}
|
|
252832
|
+
function isParsedNullCheck(value) {
|
|
252833
|
+
return value !== null;
|
|
252834
|
+
}
|
|
252835
|
+
function getLooseNullCheck(left, right) {
|
|
252836
|
+
if (!isParsedNullCheck(left) ||
|
|
252837
|
+
!isParsedNullCheck(right) ||
|
|
252838
|
+
left.strictOp !== right.strictOp ||
|
|
252839
|
+
left.operand !== right.operand ||
|
|
252840
|
+
left.comparedWith === right.comparedWith) {
|
|
252841
|
+
return null;
|
|
252842
|
+
}
|
|
252843
|
+
return `${left.operand} ${left.strictOp === '!==' ? '!=' : '=='} null`;
|
|
252844
|
+
}
|
|
252845
|
+
function collectAndLeaves(node) {
|
|
252846
|
+
if (node.type === dist$3.AST_NODE_TYPES.LogicalExpression && node.operator === '&&') {
|
|
252847
|
+
return [...collectAndLeaves(node.left), ...collectAndLeaves(node.right)];
|
|
252848
|
+
}
|
|
252849
|
+
return [node];
|
|
252850
|
+
}
|
|
252851
|
+
function isAndChainRoot(node) {
|
|
252852
|
+
return (node.parent.type !== dist$3.AST_NODE_TYPES.LogicalExpression ||
|
|
252853
|
+
node.parent.operator !== '&&');
|
|
252854
|
+
}
|
|
252855
|
+
function findLooseNullCheckMatch(parsedChecks) {
|
|
252856
|
+
for (const [firstCheckIndex, firstCheck] of parsedChecks.entries()) {
|
|
252857
|
+
if (!isParsedNullCheck(firstCheck)) {
|
|
252858
|
+
continue;
|
|
252859
|
+
}
|
|
252860
|
+
for (let secondCheckIndex = firstCheckIndex + 1; secondCheckIndex < parsedChecks.length; secondCheckIndex++) {
|
|
252861
|
+
const replacement = getLooseNullCheck(firstCheck, parsedChecks[secondCheckIndex] ?? null);
|
|
252862
|
+
if (replacement !== null) {
|
|
252863
|
+
return { firstCheckIndex, replacement, secondCheckIndex };
|
|
252864
|
+
}
|
|
252865
|
+
}
|
|
252866
|
+
}
|
|
252867
|
+
return null;
|
|
252868
|
+
}
|
|
252869
|
+
const rule$k = createRule({
|
|
252870
|
+
create(context) {
|
|
252871
|
+
const getText = (n) => context.sourceCode.getText(n);
|
|
252872
|
+
return {
|
|
252873
|
+
/**
|
|
252874
|
+
* Handles only paired null/undefined checks in the same `&&` chain.
|
|
252875
|
+
*/
|
|
252876
|
+
LogicalExpression(node) {
|
|
252877
|
+
if (node.operator !== '&&' || !isAndChainRoot(node)) {
|
|
252878
|
+
return;
|
|
252879
|
+
}
|
|
252880
|
+
const leaves = collectAndLeaves(node);
|
|
252881
|
+
const parsedChecks = leaves.map((leaf) => parseStrictNullCheck(leaf, getText));
|
|
252882
|
+
const match = findLooseNullCheckMatch(parsedChecks);
|
|
252883
|
+
if (match === null) {
|
|
252884
|
+
return;
|
|
252885
|
+
}
|
|
252886
|
+
const replacement = leaves
|
|
252887
|
+
.filter((_, index) => index !== match.secondCheckIndex)
|
|
252888
|
+
.map((leaf, index) => index === match.firstCheckIndex
|
|
252889
|
+
? match.replacement
|
|
252890
|
+
: getText(leaf))
|
|
252891
|
+
.join(' && ');
|
|
252892
|
+
context.report({
|
|
252893
|
+
fix: (fixer) => fixer.replaceText(node, replacement),
|
|
252894
|
+
messageId: 'preferLooseNullCheck',
|
|
252895
|
+
node,
|
|
252896
|
+
});
|
|
252897
|
+
},
|
|
252898
|
+
};
|
|
252899
|
+
},
|
|
252900
|
+
meta: {
|
|
252901
|
+
docs: {
|
|
252902
|
+
description: 'Prefer loose null checks over paired strict comparisons against `null` and `undefined`.',
|
|
252903
|
+
},
|
|
252904
|
+
fixable: 'code',
|
|
252905
|
+
messages: {
|
|
252906
|
+
preferLooseNullCheck: 'Prefer loose null check over paired strict comparisons against `null` and `undefined`.',
|
|
252907
|
+
},
|
|
252908
|
+
schema: [],
|
|
252909
|
+
type: 'suggestion',
|
|
252910
|
+
},
|
|
252911
|
+
name: 'prefer-loose-null-check',
|
|
252912
|
+
});
|
|
252913
|
+
|
|
252809
252914
|
function getPushCall(node) {
|
|
252810
252915
|
if (node.expression.type !== dist$3.AST_NODE_TYPES.CallExpression) {
|
|
252811
252916
|
return null;
|
|
@@ -253191,7 +253296,7 @@ const rule$h = createUntrackedRule({
|
|
|
253191
253296
|
const estreeNodeMap = tsNodeToESTreeNodeMap;
|
|
253192
253297
|
function buildFix(read) {
|
|
253193
253298
|
const untrackedAlias = findUntrackedAlias(program);
|
|
253194
|
-
const alreadyHasUntracked = untrackedAlias
|
|
253299
|
+
const alreadyHasUntracked = untrackedAlias != null;
|
|
253195
253300
|
const wrapped = buildUntrackedWrap(read, sourceCode, untrackedAlias ?? 'untracked');
|
|
253196
253301
|
if (alreadyHasUntracked) {
|
|
253197
253302
|
return (fixer) => [fixer.replaceText(read, wrapped)];
|
|
@@ -253521,13 +253626,13 @@ const VALID_CONTAINERS = new Set(['menu', 'ol', 'ul']);
|
|
|
253521
253626
|
*/
|
|
253522
253627
|
function isElement(node) {
|
|
253523
253628
|
return (typeof node === 'object' &&
|
|
253524
|
-
node
|
|
253629
|
+
node != null &&
|
|
253525
253630
|
typeof node['name'] === 'string' &&
|
|
253526
253631
|
Array.isArray(node['children']));
|
|
253527
253632
|
}
|
|
253528
253633
|
function getClosestParentElement(node) {
|
|
253529
253634
|
let current = node['parent'];
|
|
253530
|
-
while (current
|
|
253635
|
+
while (current != null) {
|
|
253531
253636
|
if (isElement(current)) {
|
|
253532
253637
|
return current;
|
|
253533
253638
|
}
|
|
@@ -254199,7 +254304,7 @@ const rule$6 = createRule({
|
|
|
254199
254304
|
if (!arr) {
|
|
254200
254305
|
continue;
|
|
254201
254306
|
}
|
|
254202
|
-
const elements = arr.elements.filter((el) => el
|
|
254307
|
+
const elements = arr.elements.filter((el) => el != null);
|
|
254203
254308
|
if (elements.length <= 1) {
|
|
254204
254309
|
continue;
|
|
254205
254310
|
}
|
|
@@ -254445,7 +254550,7 @@ const rule$3 = createRule({
|
|
|
254445
254550
|
const purityCache = new WeakMap();
|
|
254446
254551
|
const isPureArray = (arr) => {
|
|
254447
254552
|
const cachedPurity = purityCache.get(arr);
|
|
254448
|
-
if (cachedPurity
|
|
254553
|
+
if (cachedPurity != null) {
|
|
254449
254554
|
return cachedPurity;
|
|
254450
254555
|
}
|
|
254451
254556
|
if (arr.isDirty) {
|
|
@@ -254614,7 +254719,7 @@ const config = {
|
|
|
254614
254719
|
}
|
|
254615
254720
|
for (const attr of node.inputs) {
|
|
254616
254721
|
const attrValue = getLiteralStringValue(attr);
|
|
254617
|
-
if (attrValue
|
|
254722
|
+
if (attrValue != null) {
|
|
254618
254723
|
checkAttribute(context, attr, attrValue, checkers);
|
|
254619
254724
|
}
|
|
254620
254725
|
}
|
|
@@ -255120,42 +255225,43 @@ const plugin = {
|
|
|
255120
255225
|
},
|
|
255121
255226
|
rules: {
|
|
255122
255227
|
'array-as-const': rule$5,
|
|
255123
|
-
'attrs-newline': rule$
|
|
255228
|
+
'attrs-newline': rule$Q,
|
|
255124
255229
|
'class-property-naming': rule$4,
|
|
255125
|
-
'decorator-key-sort': rule$
|
|
255126
|
-
'element-newline': rule$
|
|
255230
|
+
'decorator-key-sort': rule$P,
|
|
255231
|
+
'element-newline': rule$O,
|
|
255127
255232
|
'flat-exports': rule$3,
|
|
255128
|
-
'host-attributes-sort': rule$
|
|
255129
|
-
'html-logical-properties': rule$
|
|
255130
|
-
'import-integrity': rule$
|
|
255131
|
-
'injection-token-description': rule$
|
|
255132
|
-
'no-commonjs-import-patterns': rule$
|
|
255133
|
-
'no-deep-imports': rule$
|
|
255134
|
-
'no-deep-imports-to-indexed-packages': rule$
|
|
255135
|
-
'no-duplicate-attrs': rule$
|
|
255136
|
-
'no-duplicate-id': rule$
|
|
255137
|
-
'no-duplicate-in-head': rule$
|
|
255138
|
-
'no-fully-untracked-effect': rule$
|
|
255139
|
-
'no-href-with-router-link': rule$
|
|
255140
|
-
'no-implicit-public': rule$
|
|
255141
|
-
'no-import-assertions': rule$
|
|
255142
|
-
'no-infinite-loop': rule$
|
|
255143
|
-
'no-legacy-peer-deps': rule$
|
|
255144
|
-
'no-obsolete-attrs': rule$
|
|
255145
|
-
'no-obsolete-tags': rule$
|
|
255146
|
-
'no-playwright-empty-fill': rule$
|
|
255147
|
-
'no-project-as-in-ng-template': rule$
|
|
255148
|
-
'no-redundant-type-annotation': rule$
|
|
255149
|
-
'no-repeated-signal-in-conditional': rule$
|
|
255233
|
+
'host-attributes-sort': rule$N,
|
|
255234
|
+
'html-logical-properties': rule$M,
|
|
255235
|
+
'import-integrity': rule$L,
|
|
255236
|
+
'injection-token-description': rule$K,
|
|
255237
|
+
'no-commonjs-import-patterns': rule$J,
|
|
255238
|
+
'no-deep-imports': rule$I,
|
|
255239
|
+
'no-deep-imports-to-indexed-packages': rule$H,
|
|
255240
|
+
'no-duplicate-attrs': rule$G,
|
|
255241
|
+
'no-duplicate-id': rule$F,
|
|
255242
|
+
'no-duplicate-in-head': rule$E,
|
|
255243
|
+
'no-fully-untracked-effect': rule$D,
|
|
255244
|
+
'no-href-with-router-link': rule$C,
|
|
255245
|
+
'no-implicit-public': rule$B,
|
|
255246
|
+
'no-import-assertions': rule$A,
|
|
255247
|
+
'no-infinite-loop': rule$z,
|
|
255248
|
+
'no-legacy-peer-deps': rule$y,
|
|
255249
|
+
'no-obsolete-attrs': rule$x,
|
|
255250
|
+
'no-obsolete-tags': rule$w,
|
|
255251
|
+
'no-playwright-empty-fill': rule$v,
|
|
255252
|
+
'no-project-as-in-ng-template': rule$u,
|
|
255253
|
+
'no-redundant-type-annotation': rule$t,
|
|
255254
|
+
'no-repeated-signal-in-conditional': rule$s,
|
|
255150
255255
|
'no-restricted-attr-values': rule$2,
|
|
255151
|
-
'no-side-effects-in-computed': rule$
|
|
255152
|
-
'no-signal-reads-after-await-in-reactive-context': rule$
|
|
255153
|
-
'no-string-literal-concat': rule$
|
|
255154
|
-
'no-untracked-outside-reactive-context': rule$
|
|
255155
|
-
'no-useless-untracked': rule$
|
|
255156
|
-
'object-single-line': rule$
|
|
255157
|
-
'prefer-combined-if-control-flow': rule$
|
|
255256
|
+
'no-side-effects-in-computed': rule$r,
|
|
255257
|
+
'no-signal-reads-after-await-in-reactive-context': rule$q,
|
|
255258
|
+
'no-string-literal-concat': rule$p,
|
|
255259
|
+
'no-untracked-outside-reactive-context': rule$o,
|
|
255260
|
+
'no-useless-untracked': rule$n,
|
|
255261
|
+
'object-single-line': rule$m,
|
|
255262
|
+
'prefer-combined-if-control-flow': rule$l,
|
|
255158
255263
|
'prefer-deep-imports': rule$1,
|
|
255264
|
+
'prefer-loose-null-check': rule$k,
|
|
255159
255265
|
'prefer-multi-arg-push': rule$j,
|
|
255160
255266
|
'prefer-namespace-keyword': rule$i,
|
|
255161
255267
|
'prefer-untracked-incidental-signal-reads': rule$h,
|
package/package.json
CHANGED