@angular-eslint/eslint-plugin 21.4.1-alpha.7 → 22.0.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 +2 -10
- package/dist/index.d.ts +0 -77
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -11
- package/dist/rules/contextual-lifecycle.d.ts.map +1 -1
- package/dist/rules/contextual-lifecycle.js +3 -0
- package/dist/rules/no-async-lifecycle-method.d.ts.map +1 -1
- package/dist/rules/no-async-lifecycle-method.js +1 -0
- package/dist/rules/no-empty-lifecycle-method.d.ts.map +1 -1
- package/dist/rules/no-empty-lifecycle-method.js +1 -0
- package/dist/rules/no-implicit-take-until-destroyed.js +1 -1
- package/dist/rules/prefer-inject.d.ts.map +1 -1
- package/dist/rules/prefer-inject.js +1 -0
- package/dist/rules/prefer-on-push-component-change-detection.d.ts +1 -1
- package/dist/rules/prefer-on-push-component-change-detection.d.ts.map +1 -1
- package/dist/rules/prefer-on-push-component-change-detection.js +27 -41
- package/package.json +6 -6
- package/dist/configs/README.md +0 -44
- package/dist/configs/all.json +0 -54
- package/dist/configs/recommended.json +0 -18
- package/dist/rules/no-conflicting-lifecycle.d.ts +0 -11
- package/dist/rules/no-conflicting-lifecycle.d.ts.map +0 -1
- package/dist/rules/no-conflicting-lifecycle.js +0 -74
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Please see https://github.com/angular-eslint/angular-eslint for full usage instr
|
|
|
4
4
|
|
|
5
5
|
## Premade configs
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The premade flat configs that combine these rules are provided by the umbrella [`angular-eslint`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/angular-eslint/src/configs/README.md) package.
|
|
8
8
|
|
|
9
9
|
## Rules
|
|
10
10
|
|
|
@@ -71,7 +71,7 @@ Please see https://github.com/angular-eslint/angular-eslint for full usage instr
|
|
|
71
71
|
| [`pipe-prefix`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/pipe-prefix.md) | Enforce consistent prefix for pipes. | | | |
|
|
72
72
|
| [`prefer-host-metadata-property`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-host-metadata-property.md) | Use `host` metadata property instead of `@HostBinding` and `HostListener` | | | |
|
|
73
73
|
| [`prefer-inject`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-inject.md) | Prefer using the inject() function over constructor parameter injection | :white_check_mark: | | |
|
|
74
|
-
| [`prefer-on-push-component-change-detection`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-on-push-component-change-detection.md) | Ensures
|
|
74
|
+
| [`prefer-on-push-component-change-detection`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-on-push-component-change-detection.md) | Ensures components do not opt out of the default `ChangeDetectionStrategy.OnPush` change detection strategy | :white_check_mark: | | :bulb: |
|
|
75
75
|
| [`prefer-output-emitter-ref`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-output-emitter-ref.md) | Use `OutputEmitterRef` instead of `@Output()` | | | |
|
|
76
76
|
| [`prefer-output-readonly`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-output-readonly.md) | Prefer to declare `@Output`, `OutputEmitterRef` and `OutputRef` as `readonly` since they are not supposed to be reassigned | | | :bulb: |
|
|
77
77
|
| [`prefer-signal-model`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-signal-model.md) | Use `model` instead of `input` and `output` for two-way bindings | | :wrench: | |
|
|
@@ -96,12 +96,4 @@ Please see https://github.com/angular-eslint/angular-eslint for full usage instr
|
|
|
96
96
|
|
|
97
97
|
<!-- begin deprecated rule list -->
|
|
98
98
|
|
|
99
|
-
### Deprecated
|
|
100
|
-
|
|
101
|
-
<!-- prettier-ignore-start -->
|
|
102
|
-
| Rule | Replaced by |
|
|
103
|
-
| --- | --- |
|
|
104
|
-
| [`no-conflicting-lifecycle`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/no-conflicting-lifecycle.md) | |
|
|
105
|
-
<!-- prettier-ignore-end -->
|
|
106
|
-
|
|
107
99
|
<!-- end deprecated rule list -->
|
package/dist/index.d.ts
CHANGED
|
@@ -1,78 +1,4 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
|
-
configs: {
|
|
3
|
-
all: {
|
|
4
|
-
parser: string;
|
|
5
|
-
plugins: string[];
|
|
6
|
-
rules: {
|
|
7
|
-
"@angular-eslint/component-class-suffix": string;
|
|
8
|
-
"@angular-eslint/component-max-inline-declarations": string;
|
|
9
|
-
"@angular-eslint/component-selector": string;
|
|
10
|
-
"@angular-eslint/computed-must-return": string;
|
|
11
|
-
"@angular-eslint/consistent-component-styles": string;
|
|
12
|
-
"@angular-eslint/contextual-decorator": string;
|
|
13
|
-
"@angular-eslint/contextual-lifecycle": string;
|
|
14
|
-
"@angular-eslint/directive-class-suffix": string;
|
|
15
|
-
"@angular-eslint/directive-selector": string;
|
|
16
|
-
"@angular-eslint/no-async-lifecycle-method": string;
|
|
17
|
-
"@angular-eslint/no-attribute-decorator": string;
|
|
18
|
-
"@angular-eslint/no-developer-preview": string;
|
|
19
|
-
"@angular-eslint/no-duplicates-in-metadata-arrays": string;
|
|
20
|
-
"@angular-eslint/no-empty-lifecycle-method": string;
|
|
21
|
-
"@angular-eslint/no-experimental": string;
|
|
22
|
-
"@angular-eslint/no-forward-ref": string;
|
|
23
|
-
"@angular-eslint/no-implicit-take-until-destroyed": string;
|
|
24
|
-
"@angular-eslint/no-input-prefix": string;
|
|
25
|
-
"@angular-eslint/no-input-rename": string;
|
|
26
|
-
"@angular-eslint/no-inputs-metadata-property": string;
|
|
27
|
-
"@angular-eslint/no-lifecycle-call": string;
|
|
28
|
-
"@angular-eslint/no-output-native": string;
|
|
29
|
-
"@angular-eslint/no-output-on-prefix": string;
|
|
30
|
-
"@angular-eslint/no-output-rename": string;
|
|
31
|
-
"@angular-eslint/no-outputs-metadata-property": string;
|
|
32
|
-
"@angular-eslint/no-pipe-impure": string;
|
|
33
|
-
"@angular-eslint/no-queries-metadata-property": string;
|
|
34
|
-
"@angular-eslint/no-uncalled-signals": string;
|
|
35
|
-
"@angular-eslint/pipe-prefix": string;
|
|
36
|
-
"@angular-eslint/prefer-host-metadata-property": string;
|
|
37
|
-
"@angular-eslint/prefer-inject": string;
|
|
38
|
-
"@angular-eslint/prefer-on-push-component-change-detection": string;
|
|
39
|
-
"@angular-eslint/prefer-output-emitter-ref": string;
|
|
40
|
-
"@angular-eslint/prefer-output-readonly": string;
|
|
41
|
-
"@angular-eslint/prefer-signal-model": string;
|
|
42
|
-
"@angular-eslint/prefer-signals": string;
|
|
43
|
-
"@angular-eslint/prefer-standalone": string;
|
|
44
|
-
"@angular-eslint/relative-url-prefix": string;
|
|
45
|
-
"@angular-eslint/require-lifecycle-on-prototype": string;
|
|
46
|
-
"@angular-eslint/require-localize-metadata": string;
|
|
47
|
-
"@angular-eslint/runtime-localize": string;
|
|
48
|
-
"@angular-eslint/sort-keys-in-type-decorator": string;
|
|
49
|
-
"@angular-eslint/sort-lifecycle-methods": string;
|
|
50
|
-
"@angular-eslint/use-component-selector": string;
|
|
51
|
-
"@angular-eslint/use-component-view-encapsulation": string;
|
|
52
|
-
"@angular-eslint/use-injectable-provided-in": string;
|
|
53
|
-
"@angular-eslint/use-lifecycle-interface": string;
|
|
54
|
-
"@angular-eslint/use-pipe-transform-interface": string;
|
|
55
|
-
};
|
|
56
|
-
};
|
|
57
|
-
recommended: {
|
|
58
|
-
parser: string;
|
|
59
|
-
plugins: string[];
|
|
60
|
-
rules: {
|
|
61
|
-
"@angular-eslint/contextual-lifecycle": string;
|
|
62
|
-
"@angular-eslint/no-empty-lifecycle-method": string;
|
|
63
|
-
"@angular-eslint/no-input-rename": string;
|
|
64
|
-
"@angular-eslint/no-inputs-metadata-property": string;
|
|
65
|
-
"@angular-eslint/no-output-native": string;
|
|
66
|
-
"@angular-eslint/no-output-on-prefix": string;
|
|
67
|
-
"@angular-eslint/no-output-rename": string;
|
|
68
|
-
"@angular-eslint/no-outputs-metadata-property": string;
|
|
69
|
-
"@angular-eslint/prefer-inject": string;
|
|
70
|
-
"@angular-eslint/prefer-standalone": string;
|
|
71
|
-
"@angular-eslint/use-pipe-transform-interface": string;
|
|
72
|
-
"@angular-eslint/use-lifecycle-interface": string;
|
|
73
|
-
};
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
2
|
rules: {
|
|
77
3
|
"component-class-suffix": import("@typescript-eslint/utils/ts-eslint").RuleModule<"componentClassSuffix", import("./rules/component-class-suffix").Options, import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
78
4
|
name: string;
|
|
@@ -107,9 +33,6 @@ declare const _default: {
|
|
|
107
33
|
"no-attribute-decorator": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noAttributeDecorator", [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
108
34
|
name: string;
|
|
109
35
|
};
|
|
110
|
-
"no-conflicting-lifecycle": import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/no-conflicting-lifecycle").MessageIds, [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
111
|
-
name: string;
|
|
112
|
-
};
|
|
113
36
|
"no-developer-preview": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noDeveloperPreview", [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
114
37
|
name: string;
|
|
115
38
|
};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiJA,kBAoDE"}
|
package/dist/index.js
CHANGED
|
@@ -32,11 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
const all_json_1 = __importDefault(require("./configs/all.json"));
|
|
39
|
-
const recommended_json_1 = __importDefault(require("./configs/recommended.json"));
|
|
40
35
|
const component_class_suffix_1 = __importStar(require("./rules/component-class-suffix"));
|
|
41
36
|
const component_max_inline_declarations_1 = __importStar(require("./rules/component-max-inline-declarations"));
|
|
42
37
|
const component_selector_1 = __importStar(require("./rules/component-selector"));
|
|
@@ -47,7 +42,6 @@ const directive_class_suffix_1 = __importStar(require("./rules/directive-class-s
|
|
|
47
42
|
const directive_selector_1 = __importStar(require("./rules/directive-selector"));
|
|
48
43
|
const no_async_lifecycle_method_1 = __importStar(require("./rules/no-async-lifecycle-method"));
|
|
49
44
|
const no_attribute_decorator_1 = __importStar(require("./rules/no-attribute-decorator"));
|
|
50
|
-
const no_conflicting_lifecycle_1 = __importStar(require("./rules/no-conflicting-lifecycle"));
|
|
51
45
|
const no_duplicates_in_metadata_arrays_1 = __importStar(require("./rules/no-duplicates-in-metadata-arrays"));
|
|
52
46
|
const no_empty_lifecycle_method_1 = __importStar(require("./rules/no-empty-lifecycle-method"));
|
|
53
47
|
const no_forward_ref_1 = __importStar(require("./rules/no-forward-ref"));
|
|
@@ -87,10 +81,6 @@ const no_developer_preview_1 = __importStar(require("./rules/no-developer-previe
|
|
|
87
81
|
const no_implicit_take_until_destroyed_1 = __importStar(require("./rules/no-implicit-take-until-destroyed"));
|
|
88
82
|
const computed_must_return_1 = __importStar(require("./rules/computed-must-return"));
|
|
89
83
|
module.exports = {
|
|
90
|
-
configs: {
|
|
91
|
-
all: all_json_1.default,
|
|
92
|
-
recommended: recommended_json_1.default,
|
|
93
|
-
},
|
|
94
84
|
rules: {
|
|
95
85
|
[component_class_suffix_1.RULE_NAME]: component_class_suffix_1.default,
|
|
96
86
|
[component_max_inline_declarations_1.RULE_NAME]: component_max_inline_declarations_1.default,
|
|
@@ -103,7 +93,6 @@ module.exports = {
|
|
|
103
93
|
[directive_selector_1.RULE_NAME]: directive_selector_1.default,
|
|
104
94
|
[no_async_lifecycle_method_1.RULE_NAME]: no_async_lifecycle_method_1.default,
|
|
105
95
|
[no_attribute_decorator_1.RULE_NAME]: no_attribute_decorator_1.default,
|
|
106
|
-
[no_conflicting_lifecycle_1.RULE_NAME]: no_conflicting_lifecycle_1.default,
|
|
107
96
|
[no_developer_preview_1.RULE_NAME]: no_developer_preview_1.default,
|
|
108
97
|
[no_duplicates_in_metadata_arrays_1.RULE_NAME]: no_duplicates_in_metadata_arrays_1.default,
|
|
109
98
|
[no_empty_lifecycle_method_1.RULE_NAME]: no_empty_lifecycle_method_1.default,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contextual-lifecycle.d.ts","sourceRoot":"","sources":["../../src/rules/contextual-lifecycle.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,qBAAqB,CAAC;AAC/C,eAAO,MAAM,SAAS,yBAAyB,CAAC;;;;AAEhD,
|
|
1
|
+
{"version":3,"file":"contextual-lifecycle.d.ts","sourceRoot":"","sources":["../../src/rules/contextual-lifecycle.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,qBAAqB,CAAC;AAC/C,eAAO,MAAM,SAAS,yBAAyB,CAAC;;;;AAEhD,wBAiEG;AAEH,eAAO,MAAM,mBAAmB;;CAE/B,CAAC"}
|
|
@@ -53,6 +53,9 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
|
|
|
53
53
|
[utils_1.Selectors.PIPE_CLASS_DECORATOR](node) {
|
|
54
54
|
checkContext(node, utils_1.ASTUtils.AngularClassDecorators.Pipe);
|
|
55
55
|
},
|
|
56
|
+
[utils_1.Selectors.SERVICE_CLASS_DECORATOR](node) {
|
|
57
|
+
checkContext(node, utils_1.ASTUtils.AngularClassDecorators.Service);
|
|
58
|
+
},
|
|
56
59
|
};
|
|
57
60
|
},
|
|
58
61
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-async-lifecycle-method.d.ts","sourceRoot":"","sources":["../../src/rules/no-async-lifecycle-method.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAClD,eAAO,MAAM,SAAS,8BAA8B,CAAC;;;;AAErD,
|
|
1
|
+
{"version":3,"file":"no-async-lifecycle-method.d.ts","sourceRoot":"","sources":["../../src/rules/no-async-lifecycle-method.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAClD,eAAO,MAAM,SAAS,8BAA8B,CAAC;;;;AAErD,wBA0CG;AAEH,eAAO,MAAM,mBAAmB;;CAG/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-empty-lifecycle-method.d.ts","sourceRoot":"","sources":["../../src/rules/no-empty-lifecycle-method.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAClB,wBAAwB,GACxB,8BAA8B,CAAC;AACnC,eAAO,MAAM,SAAS,8BAA8B,CAAC;;;;AAErD,
|
|
1
|
+
{"version":3,"file":"no-empty-lifecycle-method.d.ts","sourceRoot":"","sources":["../../src/rules/no-empty-lifecycle-method.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAClB,wBAAwB,GACxB,8BAA8B,CAAC;AACnC,eAAO,MAAM,SAAS,8BAA8B,CAAC;;;;AAErD,wBAuFG;AAYH,eAAO,MAAM,mBAAmB;;CAG/B,CAAC"}
|
|
@@ -79,5 +79,5 @@ function isInFactoryFunction(node) {
|
|
|
79
79
|
return false;
|
|
80
80
|
}
|
|
81
81
|
exports.RULE_DOCS_EXTENSION = {
|
|
82
|
-
rationale: `The \`takeUntilDestroyed()\` operator can automatically infer the current component's or directive's \`DestroyRef\` only when called within an injection context — specifically in constructors or field initializers of classes decorated with \`@Component\`, \`@Directive\`, \`@Injectable\`, or \`@
|
|
82
|
+
rationale: `The \`takeUntilDestroyed()\` operator can automatically infer the current component's or directive's \`DestroyRef\` only when called within an injection context — specifically in constructors or field initializers of classes decorated with \`@Component\`, \`@Directive\`, \`@Injectable\`, \`@Pipe\`, or \`@Service\`, or in factory functions (\`useFactory\` in providers or \`factory\` in InjectionTokens). When used in lifecycle methods like \`ngOnInit()\` or \`ngAfterViewInit()\`, in regular methods, in constructors of plain classes not managed by Angular's DI system, or in \`@NgModule\` classes (which don't support the \`ngOnDestroy\` lifecycle), the injection context is not available, and \`takeUntilDestroyed()\` will throw a runtime error: "NG0203: inject() must be called from an injection context." To fix this, inject \`DestroyRef\` using \`inject(DestroyRef)\` and pass it explicitly: \`takeUntilDestroyed(this.destroyRef)\`.`,
|
|
83
83
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-inject.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-inject.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AAEzB,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC;AACxC,eAAO,MAAM,SAAS,kBAAkB,CAAC;;;;AAEzC,
|
|
1
|
+
{"version":3,"file":"prefer-inject.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-inject.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AAEzB,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC;AACxC,eAAO,MAAM,SAAS,kBAAkB,CAAC;;;;AAEzC,wBAmGG;AAEH,eAAO,MAAM,mBAAmB;;CAG/B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type Options = [];
|
|
2
|
-
export type MessageIds = 'preferOnPushComponentChangeDetection' | '
|
|
2
|
+
export type MessageIds = 'preferOnPushComponentChangeDetection' | 'suggestRemoveChangeDetection';
|
|
3
3
|
export declare const RULE_NAME = "prefer-on-push-component-change-detection";
|
|
4
4
|
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, [], import("../utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
5
5
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-on-push-component-change-detection.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-on-push-component-change-detection.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAClB,sCAAsC,GACtC,
|
|
1
|
+
{"version":3,"file":"prefer-on-push-component-change-detection.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-on-push-component-change-detection.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAClB,sCAAsC,GACtC,8BAA8B,CAAC;AACnC,eAAO,MAAM,SAAS,8CAA8C,CAAC;;;;AAKrE,wBAoEG;AAEH,eAAO,MAAM,mBAAmB;;CAE/B,CAAC"}
|
|
@@ -11,54 +11,48 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
|
|
|
11
11
|
meta: {
|
|
12
12
|
type: 'suggestion',
|
|
13
13
|
docs: {
|
|
14
|
-
description: `Ensures
|
|
14
|
+
description: `Ensures components do not opt out of the default \`${STRATEGY_ON_PUSH}\` change detection strategy`,
|
|
15
|
+
recommended: 'recommended',
|
|
15
16
|
},
|
|
16
17
|
hasSuggestions: true,
|
|
17
18
|
schema: [],
|
|
18
19
|
messages: {
|
|
19
|
-
preferOnPushComponentChangeDetection: `
|
|
20
|
-
|
|
20
|
+
preferOnPushComponentChangeDetection: `Components should not opt out of the default \`${STRATEGY_ON_PUSH}\` change detection strategy`,
|
|
21
|
+
suggestRemoveChangeDetection: `Remove \`${METADATA_PROPERTY_NAME}\` to use the default (\`${STRATEGY_ON_PUSH}\`)`,
|
|
21
22
|
},
|
|
22
23
|
},
|
|
23
24
|
defaultOptions: [],
|
|
24
25
|
create(context) {
|
|
26
|
+
const sourceCode = context.sourceCode;
|
|
25
27
|
const changeDetectionMetadataProperty = utils_1.Selectors.metadataProperty(METADATA_PROPERTY_NAME);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
/**
|
|
29
|
+
* As of Angular v22 OnPush is the default change detection strategy, so a
|
|
30
|
+
* component only needs to be reported when it explicitly opts out of it by
|
|
31
|
+
* setting a non-OnPush `ChangeDetectionStrategy` member (e.g. `Eager`, or
|
|
32
|
+
* the deprecated `Default`). Omitting `changeDetection` entirely, or setting
|
|
33
|
+
* it to `ChangeDetectionStrategy.OnPush`, is the desired default and is not
|
|
34
|
+
* reported.
|
|
35
|
+
*/
|
|
36
|
+
const onPushOptOutProperty = `${utils_1.Selectors.COMPONENT_CLASS_DECORATOR} > CallExpression > ObjectExpression > ${changeDetectionMetadataProperty}[value.object.name='ChangeDetectionStrategy'][value.property.name!='OnPush']`;
|
|
32
37
|
return {
|
|
33
|
-
[
|
|
38
|
+
[onPushOptOutProperty](node) {
|
|
39
|
+
const { value } = node;
|
|
40
|
+
// The selector guarantees a `ChangeDetectionStrategy.<member>` value;
|
|
41
|
+
// this narrows the type for the fixer.
|
|
42
|
+
if (!utils_1.ASTUtils.isMemberExpression(value)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
34
45
|
context.report({
|
|
35
|
-
node:
|
|
46
|
+
node: value.property,
|
|
36
47
|
messageId: 'preferOnPushComponentChangeDetection',
|
|
37
48
|
suggest: [
|
|
38
49
|
{
|
|
39
|
-
messageId: '
|
|
50
|
+
messageId: 'suggestRemoveChangeDetection',
|
|
40
51
|
fix: (fixer) => {
|
|
41
|
-
|
|
42
|
-
return [
|
|
43
|
-
utils_1.RuleFixes.getImportAddFix({
|
|
44
|
-
fixer,
|
|
45
|
-
importName: 'ChangeDetectionStrategy',
|
|
46
|
-
moduleName: '@angular/core',
|
|
47
|
-
node: node.parent.parent.parent.parent,
|
|
48
|
-
}),
|
|
49
|
-
utils_1.ASTUtils.isMemberExpression(node.value)
|
|
50
|
-
? fixer.replaceText(node.value.property, 'OnPush')
|
|
51
|
-
: fixer.replaceText(node.value, STRATEGY_ON_PUSH),
|
|
52
|
-
].filter(utils_1.isNotNullOrUndefined);
|
|
53
|
-
}
|
|
52
|
+
const importDeclarations = utils_1.ASTUtils.getImportDeclarations(node, '@angular/core') ?? [];
|
|
54
53
|
return [
|
|
55
|
-
utils_1.RuleFixes.
|
|
56
|
-
|
|
57
|
-
importName: 'ChangeDetectionStrategy',
|
|
58
|
-
moduleName: '@angular/core',
|
|
59
|
-
node: node.parent,
|
|
60
|
-
}),
|
|
61
|
-
utils_1.RuleFixes.getDecoratorPropertyAddFix(node, fixer, `${METADATA_PROPERTY_NAME}: ${STRATEGY_ON_PUSH}`),
|
|
54
|
+
utils_1.RuleFixes.getNodeToCommaRemoveFix(sourceCode, node, fixer),
|
|
55
|
+
utils_1.RuleFixes.getImportRemoveFix(sourceCode, importDeclarations, 'ChangeDetectionStrategy', fixer),
|
|
62
56
|
].filter(utils_1.isNotNullOrUndefined);
|
|
63
57
|
},
|
|
64
58
|
},
|
|
@@ -68,14 +62,6 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
|
|
|
68
62
|
};
|
|
69
63
|
},
|
|
70
64
|
});
|
|
71
|
-
function nodeToReport(node) {
|
|
72
|
-
if (!utils_1.ASTUtils.isProperty(node)) {
|
|
73
|
-
return node;
|
|
74
|
-
}
|
|
75
|
-
return utils_1.ASTUtils.isMemberExpression(node.value)
|
|
76
|
-
? node.value.property
|
|
77
|
-
: node.value;
|
|
78
|
-
}
|
|
79
65
|
exports.RULE_DOCS_EXTENSION = {
|
|
80
|
-
rationale: `
|
|
66
|
+
rationale: `As of Angular v22, \`${STRATEGY_ON_PUSH}\` is the default change detection strategy: a component that does not specify \`${METADATA_PROPERTY_NAME}\` is checked using OnPush. This brings new code in line with zoneless being the default and with Angular's goal of performance by default, and means it is no longer necessary to set \`${STRATEGY_ON_PUSH}\` explicitly. The previous default, \`ChangeDetectionStrategy.Default\`, has been renamed to \`ChangeDetectionStrategy.Eager\`. When you run \`ng update\`, the v22 migration adds an explicit \`ChangeDetectionStrategy.Eager\` to existing components that relied on the old implicit default, so that they keep behaving as before.\n\nBecause omitting \`${METADATA_PROPERTY_NAME}\` (or setting it to \`${STRATEGY_ON_PUSH}\`) already gives you OnPush, this rule does not require you to declare it. Instead it reports components that explicitly opt out of OnPush by setting \`ChangeDetectionStrategy.Eager\` (or the deprecated \`ChangeDetectionStrategy.Default\`) — including the components the migration marked as \`Eager\` — so you can review them and adopt OnPush where it is safe to do so. The suggestion removes the \`${METADATA_PROPERTY_NAME}\` property entirely (along with the now-unused \`ChangeDetectionStrategy\` import), relying on the v22 default rather than setting \`${STRATEGY_ON_PUSH}\` explicitly. Note that switching a component from eager checking to OnPush can change its runtime behaviour, so apply the suggestion deliberately and make sure the component uses immutable data patterns (creating new object references when data changes).`,
|
|
81
67
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-eslint/eslint-plugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "22.0.0",
|
|
4
4
|
"description": "ESLint plugin for Angular applications, following https://angular.dev/style-guide",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"ts-api-utils": "^2.1.0",
|
|
22
|
-
"@angular-eslint/bundled-angular-compiler": "
|
|
23
|
-
"@angular-eslint/utils": "
|
|
22
|
+
"@angular-eslint/bundled-angular-compiler": "22.0.0",
|
|
23
|
+
"@angular-eslint/utils": "22.0.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@angular-eslint/test-utils": "
|
|
26
|
+
"@angular-eslint/test-utils": "22.0.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@typescript-eslint/utils": "^
|
|
30
|
-
"eslint": "^
|
|
29
|
+
"@typescript-eslint/utils": "^8.0.0",
|
|
30
|
+
"eslint": "^9.0.0 || ^10.0.0",
|
|
31
31
|
"typescript": "*"
|
|
32
32
|
},
|
|
33
33
|
"gitHead": "e2006e5e9c99e5a943d1a999e0efa5247d29ec24"
|
package/dist/configs/README.md
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Premade configs
|
|
2
|
-
|
|
3
|
-
These configs exist for your convenience. They contain configuration intended to save you time and effort when configuring your project by disabling rules known to conflict with this repository, or cause issues in Angular codebases.
|
|
4
|
-
|
|
5
|
-
## `all`
|
|
6
|
-
|
|
7
|
-
Quite simply, this enables all the possible rules from `@angular-eslint/eslint-plugin`. It is unlikely this will be applicable in real-world projects, but some folks find this useful to have as a reference.
|
|
8
|
-
|
|
9
|
-
## `recommended`
|
|
10
|
-
|
|
11
|
-
The recommended set is an **_opinionated_** set of Angular-specific rules that we think you should use because:
|
|
12
|
-
|
|
13
|
-
1. They help you adhere to Angular best practices.
|
|
14
|
-
2. They help catch probable issue vectors in your code.
|
|
15
|
-
|
|
16
|
-
That being said, it is not the only way to use `@angular-eslint/eslint-plugin`, nor is it the way that will necessarily work 100% for your project/company. It has been built based off of two main things:
|
|
17
|
-
|
|
18
|
-
1. Angular best practices collected and collated from places like:
|
|
19
|
-
- [Angular repo](https://github.com/angular/angular).
|
|
20
|
-
- [Angular documentation](https://angular.dev).
|
|
21
|
-
- Advice from the Angular Team at Google.
|
|
22
|
-
2. The combined state of community contributed rulesets at the time of creation.
|
|
23
|
-
|
|
24
|
-
It is strongly encouraged to combine the recommended Angular rules with the recommended configs from `typescript-eslint` (https://typescript-eslint.io/linting/configs/#recommended-configurations), and this is what our schematics will generate for you automatically.
|
|
25
|
-
|
|
26
|
-
We will not change/add new rules to the recommended set unless we release a major package version (i.e. it is seen as a breaking change).
|
|
27
|
-
|
|
28
|
-
### Altering the recommended set to suit your project
|
|
29
|
-
|
|
30
|
-
If you disagree with a rule (or it disagrees with your codebase), consider using your local config to change the rule config so it works for your project.
|
|
31
|
-
|
|
32
|
-
```cjson
|
|
33
|
-
{
|
|
34
|
-
"extends": ["plugin:@angular-eslint/recommended"],
|
|
35
|
-
"rules": {
|
|
36
|
-
// our project thinks using renaming inputs is ok
|
|
37
|
-
"@angular-eslint/no-input-rename": "off"
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Suggesting changes to the recommended set
|
|
43
|
-
|
|
44
|
-
If you feel _very_, **very**, **_very_** strongly that a specific rule should (or should not) be in the recommended ruleset, please feel free to file an issue along with a **detailed** argument explaining your reasoning. We expect to see you citing concrete evidence supporting why (or why not) a rule is considered best practice. **Please note that if your reasoning is along the lines of "it's what my project/company does", or "I don't like the rule", then we will likely close the request without discussion.**
|
package/dist/configs/all.json
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"parser": "@typescript-eslint/parser",
|
|
3
|
-
"plugins": ["@angular-eslint"],
|
|
4
|
-
"rules": {
|
|
5
|
-
"@angular-eslint/component-class-suffix": "error",
|
|
6
|
-
"@angular-eslint/component-max-inline-declarations": "error",
|
|
7
|
-
"@angular-eslint/component-selector": "error",
|
|
8
|
-
"@angular-eslint/computed-must-return": "error",
|
|
9
|
-
"@angular-eslint/consistent-component-styles": "error",
|
|
10
|
-
"@angular-eslint/contextual-decorator": "error",
|
|
11
|
-
"@angular-eslint/contextual-lifecycle": "error",
|
|
12
|
-
"@angular-eslint/directive-class-suffix": "error",
|
|
13
|
-
"@angular-eslint/directive-selector": "error",
|
|
14
|
-
"@angular-eslint/no-async-lifecycle-method": "error",
|
|
15
|
-
"@angular-eslint/no-attribute-decorator": "error",
|
|
16
|
-
"@angular-eslint/no-developer-preview": "error",
|
|
17
|
-
"@angular-eslint/no-duplicates-in-metadata-arrays": "error",
|
|
18
|
-
"@angular-eslint/no-empty-lifecycle-method": "error",
|
|
19
|
-
"@angular-eslint/no-experimental": "error",
|
|
20
|
-
"@angular-eslint/no-forward-ref": "error",
|
|
21
|
-
"@angular-eslint/no-implicit-take-until-destroyed": "error",
|
|
22
|
-
"@angular-eslint/no-input-prefix": "error",
|
|
23
|
-
"@angular-eslint/no-input-rename": "error",
|
|
24
|
-
"@angular-eslint/no-inputs-metadata-property": "error",
|
|
25
|
-
"@angular-eslint/no-lifecycle-call": "error",
|
|
26
|
-
"@angular-eslint/no-output-native": "error",
|
|
27
|
-
"@angular-eslint/no-output-on-prefix": "error",
|
|
28
|
-
"@angular-eslint/no-output-rename": "error",
|
|
29
|
-
"@angular-eslint/no-outputs-metadata-property": "error",
|
|
30
|
-
"@angular-eslint/no-pipe-impure": "error",
|
|
31
|
-
"@angular-eslint/no-queries-metadata-property": "error",
|
|
32
|
-
"@angular-eslint/no-uncalled-signals": "error",
|
|
33
|
-
"@angular-eslint/pipe-prefix": "error",
|
|
34
|
-
"@angular-eslint/prefer-host-metadata-property": "error",
|
|
35
|
-
"@angular-eslint/prefer-inject": "error",
|
|
36
|
-
"@angular-eslint/prefer-on-push-component-change-detection": "error",
|
|
37
|
-
"@angular-eslint/prefer-output-emitter-ref": "error",
|
|
38
|
-
"@angular-eslint/prefer-output-readonly": "error",
|
|
39
|
-
"@angular-eslint/prefer-signal-model": "error",
|
|
40
|
-
"@angular-eslint/prefer-signals": "error",
|
|
41
|
-
"@angular-eslint/prefer-standalone": "error",
|
|
42
|
-
"@angular-eslint/relative-url-prefix": "error",
|
|
43
|
-
"@angular-eslint/require-lifecycle-on-prototype": "error",
|
|
44
|
-
"@angular-eslint/require-localize-metadata": "error",
|
|
45
|
-
"@angular-eslint/runtime-localize": "error",
|
|
46
|
-
"@angular-eslint/sort-keys-in-type-decorator": "error",
|
|
47
|
-
"@angular-eslint/sort-lifecycle-methods": "error",
|
|
48
|
-
"@angular-eslint/use-component-selector": "error",
|
|
49
|
-
"@angular-eslint/use-component-view-encapsulation": "error",
|
|
50
|
-
"@angular-eslint/use-injectable-provided-in": "error",
|
|
51
|
-
"@angular-eslint/use-lifecycle-interface": "error",
|
|
52
|
-
"@angular-eslint/use-pipe-transform-interface": "error"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"parser": "@typescript-eslint/parser",
|
|
3
|
-
"plugins": ["@angular-eslint"],
|
|
4
|
-
"rules": {
|
|
5
|
-
"@angular-eslint/contextual-lifecycle": "error",
|
|
6
|
-
"@angular-eslint/no-empty-lifecycle-method": "error",
|
|
7
|
-
"@angular-eslint/no-input-rename": "error",
|
|
8
|
-
"@angular-eslint/no-inputs-metadata-property": "error",
|
|
9
|
-
"@angular-eslint/no-output-native": "error",
|
|
10
|
-
"@angular-eslint/no-output-on-prefix": "error",
|
|
11
|
-
"@angular-eslint/no-output-rename": "error",
|
|
12
|
-
"@angular-eslint/no-outputs-metadata-property": "error",
|
|
13
|
-
"@angular-eslint/prefer-inject": "error",
|
|
14
|
-
"@angular-eslint/prefer-standalone": "error",
|
|
15
|
-
"@angular-eslint/use-pipe-transform-interface": "error",
|
|
16
|
-
"@angular-eslint/use-lifecycle-interface": "warn"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export type Options = [];
|
|
2
|
-
export type MessageIds = 'noConflictingLifecycleInterface' | 'noConflictingLifecycleMethod';
|
|
3
|
-
export declare const RULE_NAME = "no-conflicting-lifecycle";
|
|
4
|
-
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, [], import("../utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
5
|
-
name: string;
|
|
6
|
-
};
|
|
7
|
-
export default _default;
|
|
8
|
-
export declare const RULE_DOCS_EXTENSION: {
|
|
9
|
-
rationale: string;
|
|
10
|
-
};
|
|
11
|
-
//# sourceMappingURL=no-conflicting-lifecycle.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"no-conflicting-lifecycle.d.ts","sourceRoot":"","sources":["../../src/rules/no-conflicting-lifecycle.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAClB,iCAAiC,GACjC,8BAA8B,CAAC;AACnC,eAAO,MAAM,SAAS,6BAA6B,CAAC;;;;AAWpD,wBA8EG;AAEH,eAAO,MAAM,mBAAmB;;CAG/B,CAAC"}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RULE_DOCS_EXTENSION = exports.RULE_NAME = void 0;
|
|
4
|
-
const utils_1 = require("@angular-eslint/utils");
|
|
5
|
-
const utils_2 = require("@typescript-eslint/utils");
|
|
6
|
-
const create_eslint_rule_1 = require("../utils/create-eslint-rule");
|
|
7
|
-
exports.RULE_NAME = 'no-conflicting-lifecycle';
|
|
8
|
-
const LIFECYCLE_INTERFACES = [
|
|
9
|
-
utils_1.ASTUtils.AngularLifecycleInterfaces.DoCheck,
|
|
10
|
-
utils_1.ASTUtils.AngularLifecycleInterfaces.OnChanges,
|
|
11
|
-
];
|
|
12
|
-
const LIFECYCLE_METHODS = [
|
|
13
|
-
utils_1.ASTUtils.AngularLifecycleMethods.ngDoCheck,
|
|
14
|
-
utils_1.ASTUtils.AngularLifecycleMethods.ngOnChanges,
|
|
15
|
-
];
|
|
16
|
-
exports.default = (0, create_eslint_rule_1.createESLintRule)({
|
|
17
|
-
name: exports.RULE_NAME,
|
|
18
|
-
meta: {
|
|
19
|
-
type: 'suggestion',
|
|
20
|
-
deprecated: true,
|
|
21
|
-
docs: {
|
|
22
|
-
description: 'Ensures that directives do not implement conflicting lifecycle interfaces.',
|
|
23
|
-
},
|
|
24
|
-
schema: [],
|
|
25
|
-
messages: {
|
|
26
|
-
noConflictingLifecycleInterface: `Implementing ${utils_1.ASTUtils.AngularLifecycleInterfaces.DoCheck} and ${utils_1.ASTUtils.AngularLifecycleInterfaces.OnChanges} in a class is not recommended`,
|
|
27
|
-
noConflictingLifecycleMethod: `Declaring ${utils_1.ASTUtils.AngularLifecycleMethods.ngDoCheck} and ${utils_1.ASTUtils.AngularLifecycleMethods.ngOnChanges} method in a class is not recommended`,
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
defaultOptions: [],
|
|
31
|
-
create(context) {
|
|
32
|
-
const validateInterfaces = (node) => {
|
|
33
|
-
const declaredAngularLifecycleInterfaces = utils_1.ASTUtils.getDeclaredAngularLifecycleInterfaces(node);
|
|
34
|
-
const hasInterfaceConflictingLifecycle = LIFECYCLE_INTERFACES.every((lifecycleInterface) => declaredAngularLifecycleInterfaces.includes(lifecycleInterface));
|
|
35
|
-
if (!hasInterfaceConflictingLifecycle)
|
|
36
|
-
return;
|
|
37
|
-
const declaredInterfaces = utils_1.ASTUtils.getInterfaces(node);
|
|
38
|
-
const declaredAngularLifecycleInterfacesNodes = declaredInterfaces.filter((node) => {
|
|
39
|
-
const interfaceName = utils_1.ASTUtils.getInterfaceName(node);
|
|
40
|
-
return (interfaceName && utils_1.ASTUtils.isAngularLifecycleInterface(interfaceName));
|
|
41
|
-
});
|
|
42
|
-
for (const interFaceNode of declaredAngularLifecycleInterfacesNodes) {
|
|
43
|
-
context.report({
|
|
44
|
-
node: interFaceNode,
|
|
45
|
-
messageId: 'noConflictingLifecycleInterface',
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
const validateMethods = (node) => {
|
|
50
|
-
const declaredAngularLifecycleMethods = utils_1.ASTUtils.getDeclaredAngularLifecycleMethods(node);
|
|
51
|
-
const hasMethodConflictingLifecycle = LIFECYCLE_METHODS.every((lifecycleMethod) => declaredAngularLifecycleMethods.includes(lifecycleMethod));
|
|
52
|
-
if (!hasMethodConflictingLifecycle)
|
|
53
|
-
return;
|
|
54
|
-
const declaredMethods = utils_1.ASTUtils.getDeclaredMethods(node);
|
|
55
|
-
const declaredAngularLifecycleMethodNodes = declaredMethods.filter((node) => utils_2.ASTUtils.isIdentifier(node.key) &&
|
|
56
|
-
utils_1.ASTUtils.isAngularLifecycleMethod(node.key.name));
|
|
57
|
-
for (const method of declaredAngularLifecycleMethodNodes) {
|
|
58
|
-
context.report({
|
|
59
|
-
node: method,
|
|
60
|
-
messageId: 'noConflictingLifecycleMethod',
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
return {
|
|
65
|
-
ClassDeclaration(node) {
|
|
66
|
-
validateInterfaces(node);
|
|
67
|
-
validateMethods(node);
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
exports.RULE_DOCS_EXTENSION = {
|
|
73
|
-
rationale: 'This rule was created with the intent to prevent potential issues when both DoCheck and OnChanges lifecycle hooks are implemented together, as they both deal with change detection and could create confusing or duplicated logic. However, the rule has proven to be overly broad in practice. It triggers whenever a component or directive implements both hooks, regardless of whether they actually conflict or track the same data. In reality, there are legitimate use cases where both hooks can coexist without issues—for instance, using OnChanges to respond to specific input changes while using DoCheck for custom change detection logic on different data. Because the rule cannot accurately determine whether the hooks are actually conflicting (i.e., checking the same variables), it produces false positives and has been removed from the recommended configuration. While the rule was well-intentioned, it should not be relied upon in practice.',
|
|
74
|
-
};
|