@taiga-ui/eslint-plugin-experience-next 0.471.0 → 0.473.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 +108 -7
- package/index.d.ts +3 -0
- package/index.esm.js +344 -151
- package/package.json +1 -1
- package/rules/prefer-combined-if-control-flow.d.ts +5 -0
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ export default [
|
|
|
44
44
|
| decorator-key-sort | Sorts the keys of the object passed to the `@Component/@Injectable/@NgModule/@Pipe` decorator | ✅ | 🔧 | |
|
|
45
45
|
| flat-exports | Spread nested arrays when exporting Angular entity collections | | 🔧 | |
|
|
46
46
|
| host-attributes-sort | Sort Angular host metadata attributes using configurable attribute groups | ✅ | 🔧 | |
|
|
47
|
-
| injection-token-description |
|
|
47
|
+
| injection-token-description | Require `InjectionToken` descriptions to include the token name | ✅ | 🔧 | |
|
|
48
48
|
| no-deep-imports | Disables deep imports of Taiga UI packages | ✅ | 🔧 | |
|
|
49
49
|
| no-deep-imports-to-indexed-packages | Disallow deep imports from packages that expose an index.ts next to ng-package.json or package.json | ✅ | 🔧 | |
|
|
50
50
|
| no-fully-untracked-effect | Disallow reactive callbacks where all signal reads are hidden inside `untracked()` | ✅ | | |
|
|
@@ -60,6 +60,7 @@ export default [
|
|
|
60
60
|
| no-untracked-outside-reactive-context | Disallow `untracked()` outside reactive callbacks, except explicit post-`await` snapshots | ✅ | 🔧 | |
|
|
61
61
|
| no-useless-untracked | Disallow provably useless `untracked()` wrappers in reactive callbacks | ✅ | 🔧 | |
|
|
62
62
|
| object-single-line | Enforce single-line formatting for single-property objects when it fits `printWidth` | ✅ | 🔧 | |
|
|
63
|
+
| prefer-combined-if-control-flow | Combine consecutive `if` statements that use the same `return`, `break`, `continue`, or `throw` | ✅ | 🔧 | |
|
|
63
64
|
| prefer-deep-imports | Allow deep imports of Taiga UI packages | | 🔧 | |
|
|
64
65
|
| prefer-multi-arg-push | Combine consecutive `.push()` calls on the same array into a single multi-argument call | ✅ | 🔧 | |
|
|
65
66
|
| prefer-untracked-incidental-signal-reads | Wrap likely-incidental signal reads with `untracked()` in reactive callbacks | ✅ | 🔧 | |
|
|
@@ -282,17 +283,25 @@ Use atomic presets when you want a custom order instead of one of the bundled al
|
|
|
282
283
|
|
|
283
284
|
## injection-token-description
|
|
284
285
|
|
|
285
|
-
<sup>`✅ Recommended`</sup>
|
|
286
|
+
<sup>`✅ Recommended`</sup> <sup>`Fixable`</sup>
|
|
286
287
|
|
|
287
|
-
The description
|
|
288
|
-
|
|
288
|
+
The description passed to `new InjectionToken(...)` must contain the name of the variable it is assigned to. The rule
|
|
289
|
+
accepts both direct string descriptions and Angular's `ngDevMode ? '...' : ''` pattern, and the autofix rewrites invalid
|
|
290
|
+
descriptions to the dev-only form. If `ngDevMode` is not declared in the file, the autofix inserts
|
|
291
|
+
`declare const ngDevMode: boolean;` after imports.
|
|
289
292
|
|
|
290
293
|
```ts
|
|
291
|
-
// ❌ error
|
|
292
|
-
|
|
294
|
+
// ❌ error
|
|
295
|
+
import {InjectionToken} from '@angular/core';
|
|
296
|
+
|
|
297
|
+
export const TUI_MY_TOKEN = new InjectionToken<string>('some description');
|
|
293
298
|
|
|
294
299
|
// ✅ after autofix
|
|
295
|
-
|
|
300
|
+
import {InjectionToken} from '@angular/core';
|
|
301
|
+
|
|
302
|
+
declare const ngDevMode: boolean;
|
|
303
|
+
|
|
304
|
+
export const TUI_MY_TOKEN = new InjectionToken<string>(ngDevMode ? '[TUI_MY_TOKEN]: some description' : '');
|
|
296
305
|
```
|
|
297
306
|
|
|
298
307
|
---
|
|
@@ -855,6 +864,98 @@ const x = {foo: bar};
|
|
|
855
864
|
|
|
856
865
|
---
|
|
857
866
|
|
|
867
|
+
## prefer-combined-if-control-flow
|
|
868
|
+
|
|
869
|
+
<sup>`✅ Recommended`</sup> <sup>`Fixable`</sup>
|
|
870
|
+
|
|
871
|
+
Combine consecutive `if` statements when they have no `else` branch and use the same `return`, `break`, `continue`, or
|
|
872
|
+
`throw` statement. The autofix merges their conditions with `||`, while intentionally skipping cases with intervening
|
|
873
|
+
code or comments that should remain a separate control-flow boundary.
|
|
874
|
+
|
|
875
|
+
```ts
|
|
876
|
+
// ❌ error
|
|
877
|
+
while (true) {
|
|
878
|
+
if (a) continue;
|
|
879
|
+
if (b && c) continue;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// ✅ after autofix
|
|
883
|
+
while (true) {
|
|
884
|
+
if (a || (b && c)) continue;
|
|
885
|
+
}
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
```ts
|
|
889
|
+
// ❌ error
|
|
890
|
+
if (a || b) {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if (c) {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// ✅ after autofix
|
|
899
|
+
if (a || b || c) {
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
```ts
|
|
905
|
+
// ❌ error
|
|
906
|
+
if (isInvalid) return result;
|
|
907
|
+
|
|
908
|
+
if (isLegacy && shouldStop) return result;
|
|
909
|
+
|
|
910
|
+
// ✅ after autofix
|
|
911
|
+
if (isInvalid || (isLegacy && shouldStop)) return result;
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
```ts
|
|
915
|
+
// ❌ error
|
|
916
|
+
while (true) {
|
|
917
|
+
if (isDone) break;
|
|
918
|
+
if (hasError) break;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// ✅ after autofix
|
|
922
|
+
while (true) {
|
|
923
|
+
if (isDone || hasError) break;
|
|
924
|
+
}
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
```ts
|
|
928
|
+
// ❌ error
|
|
929
|
+
if (isFatal) throw error;
|
|
930
|
+
|
|
931
|
+
if (isExpired && shouldAbort) throw error;
|
|
932
|
+
|
|
933
|
+
// ✅ after autofix
|
|
934
|
+
if (isFatal || (isExpired && shouldAbort)) throw error;
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
```ts
|
|
938
|
+
// not changed — different control flow
|
|
939
|
+
while (true) {
|
|
940
|
+
if (isDone) continue;
|
|
941
|
+
if (hasError) break;
|
|
942
|
+
}
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
```ts
|
|
946
|
+
// not changed — comment keeps branches separate
|
|
947
|
+
if (a) {
|
|
948
|
+
return value;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// explain why this branch exists
|
|
952
|
+
if (b) {
|
|
953
|
+
return value;
|
|
954
|
+
}
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
---
|
|
958
|
+
|
|
858
959
|
## prefer-deep-imports
|
|
859
960
|
|
|
860
961
|
<sup>`Taiga-specific`</sup> <sup>`Fixable`</sup>
|
package/index.d.ts
CHANGED
|
@@ -81,6 +81,9 @@ declare const plugin: {
|
|
|
81
81
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
82
82
|
name: string;
|
|
83
83
|
};
|
|
84
|
+
'prefer-combined-if-control-flow': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferCombinedIfControlFlow", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
85
|
+
name: string;
|
|
86
|
+
};
|
|
84
87
|
'prefer-deep-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"prefer-deep-imports", [{
|
|
85
88
|
importFilter: string[] | string;
|
|
86
89
|
strict?: boolean;
|
package/index.esm.js
CHANGED
|
@@ -914,6 +914,7 @@ var recommended = defineConfig([
|
|
|
914
914
|
'@taiga-ui/experience-next/no-untracked-outside-reactive-context': 'error',
|
|
915
915
|
'@taiga-ui/experience-next/no-useless-untracked': 'error',
|
|
916
916
|
'@taiga-ui/experience-next/object-single-line': ['error', { printWidth: 90 }],
|
|
917
|
+
'@taiga-ui/experience-next/prefer-combined-if-control-flow': 'error',
|
|
917
918
|
'@taiga-ui/experience-next/prefer-multi-arg-push': 'error',
|
|
918
919
|
'@taiga-ui/experience-next/prefer-untracked-incidental-signal-reads': 'error',
|
|
919
920
|
'@taiga-ui/experience-next/prefer-untracked-signal-getter': 'error',
|
|
@@ -1335,8 +1336,8 @@ function intersect(a, b) {
|
|
|
1335
1336
|
return a.some((type) => origin.has(type));
|
|
1336
1337
|
}
|
|
1337
1338
|
|
|
1338
|
-
const createRule$
|
|
1339
|
-
var classPropertyNaming = createRule$
|
|
1339
|
+
const createRule$i = ESLintUtils.RuleCreator((name) => name);
|
|
1340
|
+
var classPropertyNaming = createRule$i({
|
|
1340
1341
|
create(context, [configs]) {
|
|
1341
1342
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
1342
1343
|
const typeChecker = parserServices.program.getTypeChecker();
|
|
@@ -1505,9 +1506,9 @@ function isExternalPureTuple(typeChecker, type) {
|
|
|
1505
1506
|
return typeArgs.every((item) => isClassType(item));
|
|
1506
1507
|
}
|
|
1507
1508
|
|
|
1508
|
-
const createRule$
|
|
1509
|
+
const createRule$h = ESLintUtils.RuleCreator((name) => name);
|
|
1509
1510
|
const MESSAGE_ID$7 = 'spreadArrays';
|
|
1510
|
-
var flatExports = createRule$
|
|
1511
|
+
var flatExports = createRule$h({
|
|
1511
1512
|
create(context) {
|
|
1512
1513
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
1513
1514
|
const typeChecker = parserServices.program.getTypeChecker();
|
|
@@ -1667,10 +1668,7 @@ function getDecoratorMetadata(decorator, allowedNames) {
|
|
|
1667
1668
|
return null;
|
|
1668
1669
|
}
|
|
1669
1670
|
const callee = expr.callee;
|
|
1670
|
-
if (callee.type !== AST_NODE_TYPES$1.Identifier) {
|
|
1671
|
-
return null;
|
|
1672
|
-
}
|
|
1673
|
-
if (!allowedNames.has(callee.name)) {
|
|
1671
|
+
if (callee.type !== AST_NODE_TYPES$1.Identifier || !allowedNames.has(callee.name)) {
|
|
1674
1672
|
return null;
|
|
1675
1673
|
}
|
|
1676
1674
|
const arg = expr.arguments[0];
|
|
@@ -1746,8 +1744,8 @@ const PRESETS = {
|
|
|
1746
1744
|
$VUE: ['$CLASS', '$ID', '$VUE_ATTRIBUTE'],
|
|
1747
1745
|
$VUE_ATTRIBUTE: /^v-/,
|
|
1748
1746
|
};
|
|
1749
|
-
const createRule$
|
|
1750
|
-
const rule$
|
|
1747
|
+
const createRule$g = ESLintUtils.RuleCreator((name) => name);
|
|
1748
|
+
const rule$j = createRule$g({
|
|
1751
1749
|
create(context, [options]) {
|
|
1752
1750
|
const sourceCode = context.sourceCode;
|
|
1753
1751
|
const settings = {
|
|
@@ -1842,10 +1840,8 @@ function getHostObject(metadata) {
|
|
|
1842
1840
|
if (property.type !== AST_NODE_TYPES$1.Property ||
|
|
1843
1841
|
property.kind !== 'init' ||
|
|
1844
1842
|
property.computed ||
|
|
1845
|
-
property.method
|
|
1846
|
-
|
|
1847
|
-
}
|
|
1848
|
-
if (getStaticPropertyName(property.key) !== 'host') {
|
|
1843
|
+
property.method ||
|
|
1844
|
+
getStaticPropertyName(property.key) !== 'host') {
|
|
1849
1845
|
continue;
|
|
1850
1846
|
}
|
|
1851
1847
|
return property.value.type === AST_NODE_TYPES$1.ObjectExpression
|
|
@@ -2024,37 +2020,109 @@ const config$2 = {
|
|
|
2024
2020
|
|
|
2025
2021
|
const MESSAGE_ID$5 = 'invalid-injection-token-description';
|
|
2026
2022
|
const ERROR_MESSAGE$3 = "InjectionToken's description should contain token's name";
|
|
2027
|
-
const
|
|
2028
|
-
const
|
|
2023
|
+
const NG_DEV_MODE = 'ngDevMode';
|
|
2024
|
+
const createRule$f = ESLintUtils.RuleCreator((name) => name);
|
|
2025
|
+
function getVariableName(node) {
|
|
2026
|
+
if (node.parent.type !== AST_NODE_TYPES$1.VariableDeclarator) {
|
|
2027
|
+
return undefined;
|
|
2028
|
+
}
|
|
2029
|
+
const { id } = node.parent;
|
|
2030
|
+
return id.type === AST_NODE_TYPES$1.Identifier ? id.name : undefined;
|
|
2031
|
+
}
|
|
2032
|
+
function isStringLiteral$1(node) {
|
|
2033
|
+
return node.type === AST_NODE_TYPES$1.Literal && typeof node.value === 'string';
|
|
2034
|
+
}
|
|
2035
|
+
function isStringLike(node) {
|
|
2036
|
+
return isStringLiteral$1(node) || node.type === AST_NODE_TYPES$1.TemplateLiteral;
|
|
2037
|
+
}
|
|
2038
|
+
function getStringValue(node) {
|
|
2039
|
+
if (isStringLiteral$1(node)) {
|
|
2040
|
+
return node.value;
|
|
2041
|
+
}
|
|
2042
|
+
return node.quasis[0]?.value.raw || '';
|
|
2043
|
+
}
|
|
2044
|
+
function isEmptyString$1(node) {
|
|
2045
|
+
return (getStringValue(node) === '' &&
|
|
2046
|
+
(!('expressions' in node) || !node.expressions.length));
|
|
2047
|
+
}
|
|
2048
|
+
function isNgDevModeConditional(node) {
|
|
2049
|
+
return (node.type === AST_NODE_TYPES$1.ConditionalExpression &&
|
|
2050
|
+
node.test.type === AST_NODE_TYPES$1.Identifier &&
|
|
2051
|
+
node.test.name === NG_DEV_MODE &&
|
|
2052
|
+
isStringLike(node.consequent) &&
|
|
2053
|
+
isStringLike(node.alternate) &&
|
|
2054
|
+
isEmptyString$1(node.alternate));
|
|
2055
|
+
}
|
|
2056
|
+
function getDescriptionValue(node) {
|
|
2057
|
+
if (isStringLike(node)) {
|
|
2058
|
+
return getStringValue(node);
|
|
2059
|
+
}
|
|
2060
|
+
if (isNgDevModeConditional(node)) {
|
|
2061
|
+
return getStringValue(node.consequent);
|
|
2062
|
+
}
|
|
2063
|
+
return undefined;
|
|
2064
|
+
}
|
|
2065
|
+
function getDescriptionNode(node) {
|
|
2066
|
+
if (isStringLike(node)) {
|
|
2067
|
+
return node;
|
|
2068
|
+
}
|
|
2069
|
+
return isNgDevModeConditional(node) ? node.consequent : undefined;
|
|
2070
|
+
}
|
|
2071
|
+
function prependTokenName(text, name) {
|
|
2072
|
+
return `${text.slice(0, 1)}[${name}]: ${text.slice(1)}`;
|
|
2073
|
+
}
|
|
2074
|
+
function isNgDevModeVisible(sourceCode, node) {
|
|
2075
|
+
for (let scope = sourceCode.getScope(node); scope !== null; scope = scope.upper) {
|
|
2076
|
+
if (scope.variables.some((variable) => variable.name === NG_DEV_MODE)) {
|
|
2077
|
+
return true;
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
return false;
|
|
2081
|
+
}
|
|
2082
|
+
function getNgDevModeDeclarationFix(program, fixer) {
|
|
2083
|
+
const lastImport = [...program.body]
|
|
2084
|
+
.reverse()
|
|
2085
|
+
.find((statement) => statement.type === AST_NODE_TYPES$1.ImportDeclaration);
|
|
2086
|
+
if (lastImport) {
|
|
2087
|
+
return fixer.insertTextAfter(lastImport, '\n\ndeclare const ngDevMode: boolean;');
|
|
2088
|
+
}
|
|
2089
|
+
const [firstStatement] = program.body;
|
|
2090
|
+
if (firstStatement) {
|
|
2091
|
+
return fixer.insertTextBefore(firstStatement, 'declare const ngDevMode: boolean;\n\n');
|
|
2092
|
+
}
|
|
2093
|
+
return fixer.insertTextBeforeRange([0, 0], 'declare const ngDevMode: boolean;\n');
|
|
2094
|
+
}
|
|
2095
|
+
const rule$i = createRule$f({
|
|
2029
2096
|
create(context) {
|
|
2097
|
+
const { sourceCode } = context;
|
|
2098
|
+
const program = sourceCode.ast;
|
|
2099
|
+
let shouldAddNgDevModeDeclaration = true;
|
|
2030
2100
|
return {
|
|
2031
2101
|
'NewExpression[callee.name="InjectionToken"]'(node) {
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
const [description] = node?.arguments ?? [];
|
|
2035
|
-
if (!description) {
|
|
2102
|
+
const [description] = node.arguments;
|
|
2103
|
+
if (!description || description.type === AST_NODE_TYPES$1.SpreadElement) {
|
|
2036
2104
|
return;
|
|
2037
2105
|
}
|
|
2038
|
-
const
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
token = description.value;
|
|
2042
|
-
}
|
|
2043
|
-
if (description.type === AST_NODE_TYPES$1.TemplateLiteral) {
|
|
2044
|
-
token = description.quasis[0]?.value.raw || '';
|
|
2045
|
-
}
|
|
2046
|
-
if (node?.parent.type === AST_NODE_TYPES$1.VariableDeclarator) {
|
|
2047
|
-
const id = node.parent.id;
|
|
2048
|
-
if (id.type === AST_NODE_TYPES$1.Identifier) {
|
|
2049
|
-
name = id.name;
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2106
|
+
const name = getVariableName(node);
|
|
2107
|
+
const token = getDescriptionValue(description);
|
|
2108
|
+
const fixedDescription = getDescriptionNode(description);
|
|
2052
2109
|
const report = name && token && !token.includes(name);
|
|
2053
|
-
if (report) {
|
|
2110
|
+
if (report && fixedDescription) {
|
|
2054
2111
|
context.report({
|
|
2055
2112
|
fix: (fixer) => {
|
|
2056
|
-
const
|
|
2057
|
-
|
|
2113
|
+
const isNgDevModeGuarded = isNgDevModeConditional(description);
|
|
2114
|
+
const fixes = [
|
|
2115
|
+
fixer.replaceText(isNgDevModeGuarded ? fixedDescription : description, isNgDevModeGuarded
|
|
2116
|
+
? prependTokenName(sourceCode.getText(fixedDescription), name)
|
|
2117
|
+
: `${NG_DEV_MODE} ? ${prependTokenName(sourceCode.getText(fixedDescription), name)} : ''`),
|
|
2118
|
+
];
|
|
2119
|
+
if (!isNgDevModeGuarded &&
|
|
2120
|
+
shouldAddNgDevModeDeclaration &&
|
|
2121
|
+
!isNgDevModeVisible(sourceCode, description)) {
|
|
2122
|
+
shouldAddNgDevModeDeclaration = false;
|
|
2123
|
+
fixes.unshift(getNgDevModeDeclarationFix(program, fixer));
|
|
2124
|
+
}
|
|
2125
|
+
return fixes;
|
|
2058
2126
|
},
|
|
2059
2127
|
messageId: MESSAGE_ID$5,
|
|
2060
2128
|
node: description,
|
|
@@ -2092,8 +2160,8 @@ const DEFAULT_OPTIONS = {
|
|
|
2092
2160
|
importDeclaration: '^@taiga-ui*',
|
|
2093
2161
|
projectName: String.raw `(?<=^@taiga-ui/)([-\w]+)`,
|
|
2094
2162
|
};
|
|
2095
|
-
const createRule$
|
|
2096
|
-
const rule$
|
|
2163
|
+
const createRule$e = ESLintUtils.RuleCreator((name) => name);
|
|
2164
|
+
const rule$h = createRule$e({
|
|
2097
2165
|
create(context) {
|
|
2098
2166
|
const { currentProject, deepImport, ignoreImports, importDeclaration, projectName, } = { ...DEFAULT_OPTIONS, ...context.options[0] };
|
|
2099
2167
|
const hasNonCodeExtension = (source) => {
|
|
@@ -2180,13 +2248,13 @@ const rule$g = createRule$d({
|
|
|
2180
2248
|
name: 'no-deep-imports',
|
|
2181
2249
|
});
|
|
2182
2250
|
|
|
2183
|
-
const createRule$
|
|
2251
|
+
const createRule$d = ESLintUtils.RuleCreator((name) => name);
|
|
2184
2252
|
const resolveCacheByOptions = new WeakMap();
|
|
2185
2253
|
const nearestFileUpCache = new Map();
|
|
2186
2254
|
const markerCache = new Map();
|
|
2187
2255
|
const indexFileCache = new Map();
|
|
2188
2256
|
const indexExportsCache = new Map();
|
|
2189
|
-
var noDeepImportsToIndexedPackages = createRule$
|
|
2257
|
+
var noDeepImportsToIndexedPackages = createRule$d({
|
|
2190
2258
|
create(context) {
|
|
2191
2259
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
2192
2260
|
const program = parserServices.program;
|
|
@@ -2292,13 +2360,9 @@ var noDeepImportsToIndexedPackages = createRule$c({
|
|
|
2292
2360
|
return {
|
|
2293
2361
|
ImportDeclaration(node) {
|
|
2294
2362
|
const importSpecifier = node.source.value;
|
|
2295
|
-
if (typeof importSpecifier !== 'string'
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
if (!importSpecifier.includes('/')) {
|
|
2299
|
-
return;
|
|
2300
|
-
}
|
|
2301
|
-
if (!isExternalModuleSpecifier(importSpecifier)) {
|
|
2363
|
+
if (typeof importSpecifier !== 'string' ||
|
|
2364
|
+
!importSpecifier.includes('/') ||
|
|
2365
|
+
!isExternalModuleSpecifier(importSpecifier)) {
|
|
2302
2366
|
return;
|
|
2303
2367
|
}
|
|
2304
2368
|
const packageRootSpecifier = getPackageRootSpecifier(importSpecifier);
|
|
@@ -2366,10 +2430,8 @@ function getPackageRootSpecifier(importSpecifier) {
|
|
|
2366
2430
|
return pathParts[0] ?? importSpecifier;
|
|
2367
2431
|
}
|
|
2368
2432
|
function getSubpath(importSpecifier, packageRootSpecifier) {
|
|
2369
|
-
if (importSpecifier === packageRootSpecifier
|
|
2370
|
-
|
|
2371
|
-
}
|
|
2372
|
-
if (!importSpecifier.startsWith(`${packageRootSpecifier}/`)) {
|
|
2433
|
+
if (importSpecifier === packageRootSpecifier ||
|
|
2434
|
+
!importSpecifier.startsWith(`${packageRootSpecifier}/`)) {
|
|
2373
2435
|
return null;
|
|
2374
2436
|
}
|
|
2375
2437
|
return importSpecifier.slice(packageRootSpecifier.length + 1);
|
|
@@ -2444,10 +2506,8 @@ function getOrderedChildren(node) {
|
|
|
2444
2506
|
];
|
|
2445
2507
|
return children.filter((child) => child !== undefined && child !== null);
|
|
2446
2508
|
}
|
|
2447
|
-
if (node.type === AST_NODE_TYPES.BlockStatement
|
|
2448
|
-
|
|
2449
|
-
}
|
|
2450
|
-
if (node.type === AST_NODE_TYPES.Program) {
|
|
2509
|
+
if (node.type === AST_NODE_TYPES.BlockStatement ||
|
|
2510
|
+
node.type === AST_NODE_TYPES.Program) {
|
|
2451
2511
|
return node.body;
|
|
2452
2512
|
}
|
|
2453
2513
|
if (node.type === AST_NODE_TYPES.IfStatement) {
|
|
@@ -2508,10 +2568,7 @@ function getOrderedChildren(node) {
|
|
|
2508
2568
|
function walkSynchronousAst(root, visitor) {
|
|
2509
2569
|
traverse(root, true);
|
|
2510
2570
|
function traverse(node, isRoot = false) {
|
|
2511
|
-
if (visitor(node) === false) {
|
|
2512
|
-
return false;
|
|
2513
|
-
}
|
|
2514
|
-
if (!isRoot && isFunctionLike$1(node)) {
|
|
2571
|
+
if (visitor(node) === false || (!isRoot && isFunctionLike$1(node))) {
|
|
2515
2572
|
return false;
|
|
2516
2573
|
}
|
|
2517
2574
|
if (node.type === AST_NODE_TYPES.AwaitExpression) {
|
|
@@ -2792,10 +2849,8 @@ function isWritableSignalWrite(node, checker, esTreeNodeToTSNodeMap) {
|
|
|
2792
2849
|
return false;
|
|
2793
2850
|
}
|
|
2794
2851
|
const { object, property } = node.callee;
|
|
2795
|
-
if (property.type !== AST_NODE_TYPES.Identifier
|
|
2796
|
-
|
|
2797
|
-
}
|
|
2798
|
-
if (!SIGNAL_WRITE_METHODS.has(property.name)) {
|
|
2852
|
+
if (property.type !== AST_NODE_TYPES.Identifier ||
|
|
2853
|
+
!SIGNAL_WRITE_METHODS.has(property.name)) {
|
|
2799
2854
|
return false;
|
|
2800
2855
|
}
|
|
2801
2856
|
return isSignalType(object, checker, esTreeNodeToTSNodeMap);
|
|
@@ -2869,10 +2924,8 @@ const createUntrackedRule = ESLintUtils.RuleCreator((name) => `${UNTRACKED_RULES
|
|
|
2869
2924
|
function collectReadsInsideUntracked(root, checker, esTreeNodeToTSNodeMap, program) {
|
|
2870
2925
|
const reads = [];
|
|
2871
2926
|
walkSynchronousAst(root, (node) => {
|
|
2872
|
-
if (node.type !== AST_NODE_TYPES.CallExpression
|
|
2873
|
-
|
|
2874
|
-
}
|
|
2875
|
-
if (!isAngularUntrackedCall(node, program)) {
|
|
2927
|
+
if (node.type !== AST_NODE_TYPES.CallExpression ||
|
|
2928
|
+
!isAngularUntrackedCall(node, program)) {
|
|
2876
2929
|
return;
|
|
2877
2930
|
}
|
|
2878
2931
|
const [arg] = node.arguments;
|
|
@@ -2891,7 +2944,7 @@ function collectReadsInsideUntracked(root, checker, esTreeNodeToTSNodeMap, progr
|
|
|
2891
2944
|
});
|
|
2892
2945
|
return reads;
|
|
2893
2946
|
}
|
|
2894
|
-
const rule$
|
|
2947
|
+
const rule$g = createUntrackedRule({
|
|
2895
2948
|
create(context) {
|
|
2896
2949
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
2897
2950
|
const checker = parserServices.program.getTypeChecker();
|
|
@@ -2977,15 +3030,15 @@ const config$1 = {
|
|
|
2977
3030
|
},
|
|
2978
3031
|
};
|
|
2979
3032
|
|
|
2980
|
-
const createRule$
|
|
2981
|
-
const rule$
|
|
3033
|
+
const createRule$c = ESLintUtils.RuleCreator((name) => name);
|
|
3034
|
+
const rule$f = createRule$c({
|
|
2982
3035
|
create(context) {
|
|
2983
3036
|
const checkImplicitPublic = (node) => {
|
|
2984
3037
|
const classRef = getClass(node);
|
|
2985
|
-
if (!classRef ||
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
3038
|
+
if (!classRef ||
|
|
3039
|
+
node.kind === 'constructor' ||
|
|
3040
|
+
!!node?.accessibility ||
|
|
3041
|
+
node.key?.type === AST_NODE_TYPES.PrivateIdentifier) {
|
|
2989
3042
|
return;
|
|
2990
3043
|
}
|
|
2991
3044
|
const name = node?.key?.name ||
|
|
@@ -3049,9 +3102,9 @@ function getClass(node) {
|
|
|
3049
3102
|
return getClass(node.parent);
|
|
3050
3103
|
}
|
|
3051
3104
|
|
|
3052
|
-
const createRule$
|
|
3105
|
+
const createRule$b = ESLintUtils.RuleCreator((name) => name);
|
|
3053
3106
|
const LEGACY_PEER_DEPS_PATTERN = /^legacy-peer-deps\s*=\s*true$/i;
|
|
3054
|
-
const rule$
|
|
3107
|
+
const rule$e = createRule$b({
|
|
3055
3108
|
create(context) {
|
|
3056
3109
|
return {
|
|
3057
3110
|
Program(node) {
|
|
@@ -3089,8 +3142,8 @@ const rule$d = createRule$a({
|
|
|
3089
3142
|
name: 'no-legacy-peer-deps',
|
|
3090
3143
|
});
|
|
3091
3144
|
|
|
3092
|
-
const createRule$
|
|
3093
|
-
const rule$
|
|
3145
|
+
const createRule$a = ESLintUtils.RuleCreator((name) => name);
|
|
3146
|
+
const rule$d = createRule$a({
|
|
3094
3147
|
create(context) {
|
|
3095
3148
|
const services = ESLintUtils.getParserServices(context);
|
|
3096
3149
|
const checker = services.program.getTypeChecker();
|
|
@@ -3255,7 +3308,7 @@ const config = {
|
|
|
3255
3308
|
},
|
|
3256
3309
|
};
|
|
3257
3310
|
|
|
3258
|
-
const createRule$
|
|
3311
|
+
const createRule$9 = ESLintUtils.RuleCreator((name) => name);
|
|
3259
3312
|
function collectArrayExpressions(node) {
|
|
3260
3313
|
const result = [];
|
|
3261
3314
|
if (node.type === AST_NODE_TYPES.ArrayExpression) {
|
|
@@ -3281,7 +3334,7 @@ function collectArrayExpressions(node) {
|
|
|
3281
3334
|
}
|
|
3282
3335
|
return result;
|
|
3283
3336
|
}
|
|
3284
|
-
const rule$
|
|
3337
|
+
const rule$c = createRule$9({
|
|
3285
3338
|
create(context) {
|
|
3286
3339
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
3287
3340
|
const typeChecker = parserServices.program.getTypeChecker();
|
|
@@ -3409,7 +3462,7 @@ function unwrapExpression(expression) {
|
|
|
3409
3462
|
return current;
|
|
3410
3463
|
}
|
|
3411
3464
|
|
|
3412
|
-
const createRule$
|
|
3465
|
+
const createRule$8 = ESLintUtils.RuleCreator((name) => name);
|
|
3413
3466
|
function isReactiveCallback(node) {
|
|
3414
3467
|
return (node?.type === AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
3415
3468
|
node?.type === AST_NODE_TYPES.FunctionExpression);
|
|
@@ -3531,7 +3584,7 @@ function inspectComputedBody(root, inspectionContext, report) {
|
|
|
3531
3584
|
return;
|
|
3532
3585
|
});
|
|
3533
3586
|
}
|
|
3534
|
-
const rule$
|
|
3587
|
+
const rule$b = createRule$8({
|
|
3535
3588
|
create(context) {
|
|
3536
3589
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
3537
3590
|
const checker = parserServices.program.getTypeChecker();
|
|
@@ -3578,7 +3631,7 @@ const rule$a = createRule$7({
|
|
|
3578
3631
|
name: 'no-side-effects-in-computed',
|
|
3579
3632
|
});
|
|
3580
3633
|
|
|
3581
|
-
const rule$
|
|
3634
|
+
const rule$a = createUntrackedRule({
|
|
3582
3635
|
create(context) {
|
|
3583
3636
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
3584
3637
|
const checker = parserServices.program.getTypeChecker();
|
|
@@ -3627,7 +3680,7 @@ const rule$9 = createUntrackedRule({
|
|
|
3627
3680
|
name: 'no-signal-reads-after-await-in-reactive-context',
|
|
3628
3681
|
});
|
|
3629
3682
|
|
|
3630
|
-
const createRule$
|
|
3683
|
+
const createRule$7 = ESLintUtils.RuleCreator((name) => name);
|
|
3631
3684
|
function isStringLiteral(node) {
|
|
3632
3685
|
return (node.type === AST_NODE_TYPES.Literal &&
|
|
3633
3686
|
typeof node.value === 'string');
|
|
@@ -3691,7 +3744,7 @@ function hasTemplateLiteralAncestor(node) {
|
|
|
3691
3744
|
}
|
|
3692
3745
|
return false;
|
|
3693
3746
|
}
|
|
3694
|
-
const rule$
|
|
3747
|
+
const rule$9 = createRule$7({
|
|
3695
3748
|
create(context) {
|
|
3696
3749
|
const { sourceCode } = context;
|
|
3697
3750
|
let parserServices = null;
|
|
@@ -4111,7 +4164,7 @@ function buildReactiveCallReplacement(outerUntrackedCall, reactiveCall, sourceCo
|
|
|
4111
4164
|
}
|
|
4112
4165
|
return dedent$1(text, reactiveCall.loc.start.column - outerUntrackedCall.parent.loc.start.column);
|
|
4113
4166
|
}
|
|
4114
|
-
const rule$
|
|
4167
|
+
const rule$8 = createUntrackedRule({
|
|
4115
4168
|
create(context) {
|
|
4116
4169
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
4117
4170
|
const checker = parserServices.program.getTypeChecker();
|
|
@@ -4135,20 +4188,12 @@ const rule$7 = createUntrackedRule({
|
|
|
4135
4188
|
}
|
|
4136
4189
|
return {
|
|
4137
4190
|
CallExpression(node) {
|
|
4138
|
-
if (!isAngularUntrackedCall(node, program)
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
}
|
|
4145
|
-
if (isAllowedImperativeAngularContext(node)) {
|
|
4146
|
-
return;
|
|
4147
|
-
}
|
|
4148
|
-
if (isAllowedDeferredCallbackContext(node, checker, esTreeNodeToTSNodeMap)) {
|
|
4149
|
-
return;
|
|
4150
|
-
}
|
|
4151
|
-
if (isAllowedLazyAngularFactoryContext(node, program)) {
|
|
4191
|
+
if (!isAngularUntrackedCall(node, program) ||
|
|
4192
|
+
findEnclosingReactiveScope(node, program) ||
|
|
4193
|
+
findEnclosingReactiveScopeAfterAsyncBoundary(node, program) ||
|
|
4194
|
+
isAllowedImperativeAngularContext(node) ||
|
|
4195
|
+
isAllowedDeferredCallbackContext(node, checker, esTreeNodeToTSNodeMap) ||
|
|
4196
|
+
isAllowedLazyAngularFactoryContext(node, program)) {
|
|
4152
4197
|
return;
|
|
4153
4198
|
}
|
|
4154
4199
|
const reactiveCall = getFixableReactiveCall(node, program);
|
|
@@ -4255,10 +4300,8 @@ function hasOpaqueSynchronousCalls(root, checker, esTreeNodeToTSNodeMap, program
|
|
|
4255
4300
|
}
|
|
4256
4301
|
return;
|
|
4257
4302
|
}
|
|
4258
|
-
if (node.type !== AST_NODE_TYPES.CallExpression
|
|
4259
|
-
|
|
4260
|
-
}
|
|
4261
|
-
if (isAngularUntrackedCall(node, program) ||
|
|
4303
|
+
if (node.type !== AST_NODE_TYPES.CallExpression ||
|
|
4304
|
+
isAngularUntrackedCall(node, program) ||
|
|
4262
4305
|
isSignalReadCall(node, checker, esTreeNodeToTSNodeMap) ||
|
|
4263
4306
|
isWritableSignalWrite(node, checker, esTreeNodeToTSNodeMap)) {
|
|
4264
4307
|
return;
|
|
@@ -4268,7 +4311,7 @@ function hasOpaqueSynchronousCalls(root, checker, esTreeNodeToTSNodeMap, program
|
|
|
4268
4311
|
});
|
|
4269
4312
|
return found;
|
|
4270
4313
|
}
|
|
4271
|
-
const rule$
|
|
4314
|
+
const rule$7 = createUntrackedRule({
|
|
4272
4315
|
create(context) {
|
|
4273
4316
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
4274
4317
|
const checker = parserServices.program.getTypeChecker();
|
|
@@ -4289,14 +4332,12 @@ const rule$6 = createUntrackedRule({
|
|
|
4289
4332
|
return;
|
|
4290
4333
|
}
|
|
4291
4334
|
const { reads } = collectSignalUsages(arg, checker, esTreeNodeToTSNodeMap, program);
|
|
4292
|
-
if (reads.length > 0
|
|
4335
|
+
if (reads.length > 0 ||
|
|
4336
|
+
hasOpaqueSynchronousCalls(arg, checker, esTreeNodeToTSNodeMap, program)) {
|
|
4293
4337
|
// Snapshot reads inside reactive callbacks are a valid Angular
|
|
4294
4338
|
// pattern even when the snapshot later influences branching.
|
|
4295
4339
|
return;
|
|
4296
4340
|
}
|
|
4297
|
-
if (hasOpaqueSynchronousCalls(arg, checker, esTreeNodeToTSNodeMap, program)) {
|
|
4298
|
-
return;
|
|
4299
|
-
}
|
|
4300
4341
|
// Only fix when the parent is a plain ExpressionStatement so we can
|
|
4301
4342
|
// replace statement-for-statement without breaking surrounding structure.
|
|
4302
4343
|
const parent = untrackedCall.parent;
|
|
@@ -4358,8 +4399,8 @@ const rule$6 = createUntrackedRule({
|
|
|
4358
4399
|
name: 'no-useless-untracked',
|
|
4359
4400
|
});
|
|
4360
4401
|
|
|
4361
|
-
const createRule$
|
|
4362
|
-
const rule$
|
|
4402
|
+
const createRule$6 = ESLintUtils.RuleCreator((name) => name);
|
|
4403
|
+
const rule$6 = createRule$6({
|
|
4363
4404
|
create(context, [{ printWidth }]) {
|
|
4364
4405
|
const sourceCode = context.sourceCode;
|
|
4365
4406
|
const getLineEndIndex = (lineStartIndex) => {
|
|
@@ -4611,6 +4652,169 @@ const rule$5 = createRule$5({
|
|
|
4611
4652
|
name: 'object-single-line',
|
|
4612
4653
|
});
|
|
4613
4654
|
|
|
4655
|
+
const createRule$5 = ESLintUtils.RuleCreator((name) => name);
|
|
4656
|
+
const EMPTY_ARGUMENT = '__EMPTY_ARGUMENT__';
|
|
4657
|
+
function getParenthesizedInner(node) {
|
|
4658
|
+
const maybeNode = node;
|
|
4659
|
+
if (maybeNode.type === 'ParenthesizedExpression') {
|
|
4660
|
+
return maybeNode.expression ?? null;
|
|
4661
|
+
}
|
|
4662
|
+
return null;
|
|
4663
|
+
}
|
|
4664
|
+
function unwrapParenthesized(node) {
|
|
4665
|
+
let current = node;
|
|
4666
|
+
let inner = getParenthesizedInner(current);
|
|
4667
|
+
while (inner) {
|
|
4668
|
+
current = inner;
|
|
4669
|
+
inner = getParenthesizedInner(current);
|
|
4670
|
+
}
|
|
4671
|
+
return current;
|
|
4672
|
+
}
|
|
4673
|
+
function isSupportedControlFlowStatement(node) {
|
|
4674
|
+
return (node.type === AST_NODE_TYPES.BreakStatement ||
|
|
4675
|
+
node.type === AST_NODE_TYPES.ContinueStatement ||
|
|
4676
|
+
node.type === AST_NODE_TYPES.ReturnStatement ||
|
|
4677
|
+
node.type === AST_NODE_TYPES.ThrowStatement);
|
|
4678
|
+
}
|
|
4679
|
+
function getControlFlowStatement(node) {
|
|
4680
|
+
if (isSupportedControlFlowStatement(node)) {
|
|
4681
|
+
return node;
|
|
4682
|
+
}
|
|
4683
|
+
if (node.type === AST_NODE_TYPES.BlockStatement &&
|
|
4684
|
+
node.body.length === 1 &&
|
|
4685
|
+
isSupportedControlFlowStatement(node.body[0])) {
|
|
4686
|
+
return node.body[0];
|
|
4687
|
+
}
|
|
4688
|
+
return null;
|
|
4689
|
+
}
|
|
4690
|
+
function getControlFlowSignature(node, sourceCode) {
|
|
4691
|
+
if (node.alternate) {
|
|
4692
|
+
return null;
|
|
4693
|
+
}
|
|
4694
|
+
const controlFlowStatement = getControlFlowStatement(node.consequent);
|
|
4695
|
+
if (!controlFlowStatement) {
|
|
4696
|
+
return null;
|
|
4697
|
+
}
|
|
4698
|
+
switch (controlFlowStatement.type) {
|
|
4699
|
+
case AST_NODE_TYPES.BreakStatement:
|
|
4700
|
+
return controlFlowStatement.label
|
|
4701
|
+
? `break:${sourceCode.getText(controlFlowStatement.label)}`
|
|
4702
|
+
: `break:${EMPTY_ARGUMENT}`;
|
|
4703
|
+
case AST_NODE_TYPES.ContinueStatement:
|
|
4704
|
+
return controlFlowStatement.label
|
|
4705
|
+
? `continue:${sourceCode.getText(controlFlowStatement.label)}`
|
|
4706
|
+
: `continue:${EMPTY_ARGUMENT}`;
|
|
4707
|
+
case AST_NODE_TYPES.ReturnStatement:
|
|
4708
|
+
return controlFlowStatement.argument
|
|
4709
|
+
? `return:${sourceCode.getText(unwrapParenthesized(controlFlowStatement.argument))}`
|
|
4710
|
+
: `return:${EMPTY_ARGUMENT}`;
|
|
4711
|
+
case AST_NODE_TYPES.ThrowStatement:
|
|
4712
|
+
return `throw:${sourceCode.getText(unwrapParenthesized(controlFlowStatement.argument))}`;
|
|
4713
|
+
}
|
|
4714
|
+
}
|
|
4715
|
+
function hasNonWhitespaceBetween(sourceCode, left, right) {
|
|
4716
|
+
return sourceCode.text.slice(left.range[1], right.range[0]).trim() !== '';
|
|
4717
|
+
}
|
|
4718
|
+
function needsParenthesesInOrChain(node) {
|
|
4719
|
+
if (getParenthesizedInner(node)) {
|
|
4720
|
+
return false;
|
|
4721
|
+
}
|
|
4722
|
+
switch (node.type) {
|
|
4723
|
+
case AST_NODE_TYPES.AssignmentExpression:
|
|
4724
|
+
case AST_NODE_TYPES.ConditionalExpression:
|
|
4725
|
+
case AST_NODE_TYPES.SequenceExpression:
|
|
4726
|
+
case AST_NODE_TYPES.TSAsExpression:
|
|
4727
|
+
case AST_NODE_TYPES.TSSatisfiesExpression:
|
|
4728
|
+
case AST_NODE_TYPES.YieldExpression:
|
|
4729
|
+
return true;
|
|
4730
|
+
case AST_NODE_TYPES.LogicalExpression:
|
|
4731
|
+
return node.operator !== '||';
|
|
4732
|
+
default:
|
|
4733
|
+
return false;
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4736
|
+
function renderTest(node, sourceCode) {
|
|
4737
|
+
const text = sourceCode.getText(node);
|
|
4738
|
+
return needsParenthesesInOrChain(node) ? `(${text})` : text;
|
|
4739
|
+
}
|
|
4740
|
+
const rule$5 = createRule$5({
|
|
4741
|
+
create(context) {
|
|
4742
|
+
const { sourceCode } = context;
|
|
4743
|
+
function checkBody(statements) {
|
|
4744
|
+
let i = 0;
|
|
4745
|
+
while (i < statements.length) {
|
|
4746
|
+
const statement = statements[i];
|
|
4747
|
+
if (statement.type !== AST_NODE_TYPES.IfStatement) {
|
|
4748
|
+
i++;
|
|
4749
|
+
continue;
|
|
4750
|
+
}
|
|
4751
|
+
const signature = getControlFlowSignature(statement, sourceCode);
|
|
4752
|
+
if (!signature) {
|
|
4753
|
+
i++;
|
|
4754
|
+
continue;
|
|
4755
|
+
}
|
|
4756
|
+
const group = [statement];
|
|
4757
|
+
let j = i + 1;
|
|
4758
|
+
while (j < statements.length) {
|
|
4759
|
+
const nextStatement = statements[j];
|
|
4760
|
+
if (nextStatement.type !== AST_NODE_TYPES.IfStatement) {
|
|
4761
|
+
break;
|
|
4762
|
+
}
|
|
4763
|
+
if (!hasNonWhitespaceBetween(sourceCode, group[group.length - 1], nextStatement) &&
|
|
4764
|
+
sourceCode.getCommentsInside(nextStatement).length === 0 &&
|
|
4765
|
+
getControlFlowSignature(nextStatement, sourceCode) === signature) {
|
|
4766
|
+
group.push(nextStatement);
|
|
4767
|
+
j++;
|
|
4768
|
+
continue;
|
|
4769
|
+
}
|
|
4770
|
+
break;
|
|
4771
|
+
}
|
|
4772
|
+
if (group.length > 1) {
|
|
4773
|
+
for (const [index, ifStatement] of group.entries()) {
|
|
4774
|
+
context.report({
|
|
4775
|
+
...(index === 0
|
|
4776
|
+
? {
|
|
4777
|
+
fix(fixer) {
|
|
4778
|
+
const firstIf = group[0];
|
|
4779
|
+
const lastIf = group[group.length - 1];
|
|
4780
|
+
const condition = group
|
|
4781
|
+
.map((item) => renderTest(item.test, sourceCode))
|
|
4782
|
+
.join(' || ');
|
|
4783
|
+
return fixer.replaceTextRange([firstIf.range[0], lastIf.range[1]], `if (${condition}) ${sourceCode.getText(firstIf.consequent)}`);
|
|
4784
|
+
},
|
|
4785
|
+
}
|
|
4786
|
+
: {}),
|
|
4787
|
+
messageId: 'preferCombinedIfControlFlow',
|
|
4788
|
+
node: ifStatement,
|
|
4789
|
+
});
|
|
4790
|
+
}
|
|
4791
|
+
}
|
|
4792
|
+
i = j;
|
|
4793
|
+
}
|
|
4794
|
+
}
|
|
4795
|
+
return {
|
|
4796
|
+
BlockStatement(node) {
|
|
4797
|
+
checkBody(node.body);
|
|
4798
|
+
},
|
|
4799
|
+
Program(node) {
|
|
4800
|
+
checkBody(node.body);
|
|
4801
|
+
},
|
|
4802
|
+
};
|
|
4803
|
+
},
|
|
4804
|
+
meta: {
|
|
4805
|
+
docs: {
|
|
4806
|
+
description: 'Combine consecutive if statements that use the same return, break, continue, or throw statement into a single if statement.',
|
|
4807
|
+
},
|
|
4808
|
+
fixable: 'code',
|
|
4809
|
+
messages: {
|
|
4810
|
+
preferCombinedIfControlFlow: 'Combine consecutive if statements with identical return, break, continue, or throw statements.',
|
|
4811
|
+
},
|
|
4812
|
+
schema: [],
|
|
4813
|
+
type: 'suggestion',
|
|
4814
|
+
},
|
|
4815
|
+
name: 'prefer-combined-if-control-flow',
|
|
4816
|
+
});
|
|
4817
|
+
|
|
4614
4818
|
const MESSAGE_ID$1 = 'prefer-deep-imports';
|
|
4615
4819
|
const ERROR_MESSAGE = 'Import via root entry point is prohibited when nested entry points exist';
|
|
4616
4820
|
const createRule$4 = ESLintUtils.RuleCreator(() => ERROR_MESSAGE);
|
|
@@ -4628,14 +4832,10 @@ var preferDeepImports = createRule$4({
|
|
|
4628
4832
|
return;
|
|
4629
4833
|
}
|
|
4630
4834
|
const rootPackageName = getRootPackageName(rawImportPath);
|
|
4631
|
-
if (!rootPackageName
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
return;
|
|
4636
|
-
}
|
|
4637
|
-
if (!isStrictMode &&
|
|
4638
|
-
isAlreadyNestedImport(rawImportPath, rootPackageName)) {
|
|
4835
|
+
if (!rootPackageName ||
|
|
4836
|
+
!allowedPackages.includes(rootPackageName) ||
|
|
4837
|
+
(!isStrictMode &&
|
|
4838
|
+
isAlreadyNestedImport(rawImportPath, rootPackageName))) {
|
|
4639
4839
|
return;
|
|
4640
4840
|
}
|
|
4641
4841
|
const importedSymbols = extractNamedImportedSymbols(node);
|
|
@@ -4866,10 +5066,7 @@ function mapSymbolsToEntryPointsUsingTypeChecker(importedSymbols, candidateEntry
|
|
|
4866
5066
|
for (const importedSymbol of importedSymbols) {
|
|
4867
5067
|
for (const relativeEntryDir of candidateEntryPoints) {
|
|
4868
5068
|
const exportedNames = exportTableByEntryPoint.get(relativeEntryDir);
|
|
4869
|
-
if (!exportedNames) {
|
|
4870
|
-
continue;
|
|
4871
|
-
}
|
|
4872
|
-
if (!exportedNames.has(importedSymbol)) {
|
|
5069
|
+
if (!exportedNames?.has(importedSymbol)) {
|
|
4873
5070
|
continue;
|
|
4874
5071
|
}
|
|
4875
5072
|
symbolToEntryPoint.set(importedSymbol, relativeEntryDir);
|
|
@@ -5152,10 +5349,8 @@ function isDomImperativeCall(node, checker, esTreeNodeToTSNodeMap) {
|
|
|
5152
5349
|
}
|
|
5153
5350
|
const signature = checker.getResolvedSignature(tsNode);
|
|
5154
5351
|
const declaration = signature?.declaration;
|
|
5155
|
-
if (!declaration
|
|
5156
|
-
|
|
5157
|
-
}
|
|
5158
|
-
if (!LIB_DOM_FILE_PATTERN.test(declaration.getSourceFile().fileName)) {
|
|
5352
|
+
if (!declaration ||
|
|
5353
|
+
!LIB_DOM_FILE_PATTERN.test(declaration.getSourceFile().fileName)) {
|
|
5159
5354
|
return false;
|
|
5160
5355
|
}
|
|
5161
5356
|
const returnType = checker.typeToString(checker.getReturnTypeOfSignature(signature));
|
|
@@ -5387,18 +5582,15 @@ function getReturnedExpression(node) {
|
|
|
5387
5582
|
}
|
|
5388
5583
|
function getWrappedSignalGetter(node, checker, esTreeNodeToTSNodeMap) {
|
|
5389
5584
|
const [arg] = node.arguments;
|
|
5390
|
-
if (!arg ||
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
arg.type !== AST_NODE_TYPES.FunctionExpression) {
|
|
5585
|
+
if (!arg ||
|
|
5586
|
+
arg.type === AST_NODE_TYPES.SpreadElement ||
|
|
5587
|
+
(arg.type !== AST_NODE_TYPES.ArrowFunctionExpression &&
|
|
5588
|
+
arg.type !== AST_NODE_TYPES.FunctionExpression)) {
|
|
5395
5589
|
return null;
|
|
5396
5590
|
}
|
|
5397
5591
|
const body = getReturnedExpression(arg);
|
|
5398
|
-
if (body?.type !== AST_NODE_TYPES.CallExpression
|
|
5399
|
-
|
|
5400
|
-
}
|
|
5401
|
-
if (!isSignalReadCall(body, checker, esTreeNodeToTSNodeMap)) {
|
|
5592
|
+
if (body?.type !== AST_NODE_TYPES.CallExpression ||
|
|
5593
|
+
!isSignalReadCall(body, checker, esTreeNodeToTSNodeMap)) {
|
|
5402
5594
|
return null;
|
|
5403
5595
|
}
|
|
5404
5596
|
const getter = unwrapExpression(body.callee);
|
|
@@ -5871,24 +6063,25 @@ const plugin = {
|
|
|
5871
6063
|
'class-property-naming': classPropertyNaming,
|
|
5872
6064
|
'decorator-key-sort': config$3,
|
|
5873
6065
|
'flat-exports': flatExports,
|
|
5874
|
-
'host-attributes-sort': rule$
|
|
6066
|
+
'host-attributes-sort': rule$j,
|
|
5875
6067
|
'html-logical-properties': config$2,
|
|
5876
|
-
'injection-token-description': rule$
|
|
5877
|
-
'no-deep-imports': rule$
|
|
6068
|
+
'injection-token-description': rule$i,
|
|
6069
|
+
'no-deep-imports': rule$h,
|
|
5878
6070
|
'no-deep-imports-to-indexed-packages': noDeepImportsToIndexedPackages,
|
|
5879
|
-
'no-fully-untracked-effect': rule$
|
|
6071
|
+
'no-fully-untracked-effect': rule$g,
|
|
5880
6072
|
'no-href-with-router-link': config$1,
|
|
5881
|
-
'no-implicit-public': rule$
|
|
5882
|
-
'no-legacy-peer-deps': rule$
|
|
5883
|
-
'no-playwright-empty-fill': rule$
|
|
6073
|
+
'no-implicit-public': rule$f,
|
|
6074
|
+
'no-legacy-peer-deps': rule$e,
|
|
6075
|
+
'no-playwright-empty-fill': rule$d,
|
|
5884
6076
|
'no-project-as-in-ng-template': config,
|
|
5885
|
-
'no-redundant-type-annotation': rule$
|
|
5886
|
-
'no-side-effects-in-computed': rule$
|
|
5887
|
-
'no-signal-reads-after-await-in-reactive-context': rule$
|
|
5888
|
-
'no-string-literal-concat': rule$
|
|
5889
|
-
'no-untracked-outside-reactive-context': rule$
|
|
5890
|
-
'no-useless-untracked': rule$
|
|
5891
|
-
'object-single-line': rule$
|
|
6077
|
+
'no-redundant-type-annotation': rule$c,
|
|
6078
|
+
'no-side-effects-in-computed': rule$b,
|
|
6079
|
+
'no-signal-reads-after-await-in-reactive-context': rule$a,
|
|
6080
|
+
'no-string-literal-concat': rule$9,
|
|
6081
|
+
'no-untracked-outside-reactive-context': rule$8,
|
|
6082
|
+
'no-useless-untracked': rule$7,
|
|
6083
|
+
'object-single-line': rule$6,
|
|
6084
|
+
'prefer-combined-if-control-flow': rule$5,
|
|
5892
6085
|
'prefer-deep-imports': preferDeepImports,
|
|
5893
6086
|
'prefer-multi-arg-push': rule$4,
|
|
5894
6087
|
'prefer-untracked-incidental-signal-reads': rule$3,
|
package/package.json
CHANGED