Skip to content

Commit 8a5884d

Browse files
authored
fix(eslint): fix inject function based injection not detecting store (#3936)
Closes #3834
1 parent 0ecf0d3 commit 8a5884d

File tree

2 files changed

+81
-5
lines changed

2 files changed

+81
-5
lines changed

modules/eslint-plugin/spec/rules/no-store-subscription.spec.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,33 @@ class Ok4 {
5858
this.items$ = store.pipe(select(selectItems))
5959
this.metrics$ = store.select(selectMetrics)
6060
}
61+
}`,
62+
`
63+
import { Store } from '@ngrx/store'
64+
import { inject } from '@angular/core'
65+
66+
class Ok5 {
67+
readonly items$: Observable<readonly Item[]>
68+
readonly metrics$: Observable<Metric>
69+
readonly store = inject(Store)
70+
71+
constructor() {
72+
this.items$ = store.pipe(select(selectItems))
73+
this.metrics$ = store.select(selectMetrics)
74+
}
75+
}`,
76+
`
77+
import { Store } from '@ngrx/store'
78+
import { inject } from 'some-other-package'
79+
80+
class Ok6 {
81+
readonly items$: Observable<readonly Item[]>
82+
readonly metrics$: Observable<Metric>
83+
readonly store = inject(Store)
84+
85+
constructor() {
86+
store.pipe(select(selectItems)).subscribe()
87+
}
6188
}`,
6289
];
6390

@@ -136,7 +163,7 @@ class NotOk6 {
136163
fromFixture(`
137164
import { Store } from '@ngrx/store'
138165
139-
class NotOk6 {
166+
class NotOk7 {
140167
readonly items: readonly Item[]
141168
142169
constructor(store: Store) {
@@ -147,7 +174,7 @@ class NotOk6 {
147174
fromFixture(`
148175
import { Store } from '@ngrx/store'
149176
150-
class NotOk7 {
177+
class NotOk8 {
151178
readonly control = new FormControl()
152179
153180
constructor(store: Store) {
@@ -156,6 +183,35 @@ class NotOk7 {
156183
~~~~~~~~~ [${messageId}]
157184
})
158185
}
186+
}`),
187+
fromFixture(`
188+
import { Store } from '@ngrx/store'
189+
import { inject } from '@angular/core'
190+
191+
class NotOk9 {
192+
readonly control = new FormControl()
193+
store = inject(Store)
194+
195+
constructor() {
196+
this.control.valueChanges.subscribe(() => {
197+
store.pipe(select(selectItems)).subscribe()
198+
~~~~~~~~~ [${messageId}]
199+
})
200+
}
201+
}`),
202+
fromFixture(`
203+
import { Store } from '@ngrx/store'
204+
import { inject } from '@angular/core'
205+
206+
class NotOk10 {
207+
readonly items$: Observable<readonly Item[]>
208+
readonly metrics$: Observable<Metric>
209+
readonly store = inject(Store)
210+
211+
constructor() {
212+
store.pipe(select(selectItems)).subscribe()
213+
~~~~~~~~~ [${messageId}]
214+
}
159215
}`),
160216
];
161217

modules/eslint-plugin/src/utils/helper-functions/utils.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ import {
1313
isProgram,
1414
isProperty,
1515
isPropertyDefinition,
16-
isTemplateElement,
17-
isTemplateLiteral,
1816
isTSTypeAnnotation,
1917
isTSTypeReference,
18+
isTemplateElement,
19+
isTemplateLiteral,
2020
} from './guards';
2121
import { NGRX_MODULE_PATHS } from './ngrx-modules';
2222

@@ -30,7 +30,8 @@ type InjectedParameter =
3030
| ConstructorFunctionExpression
3131
| (TSESTree.TSParameterProperty & {
3232
parent: ConstructorFunctionExpression;
33-
});
33+
})
34+
| TSESTree.PropertyDefinition;
3435
};
3536
type InjectedParameterWithSourceCode = Readonly<{
3637
identifiers?: readonly InjectedParameter[];
@@ -315,6 +316,12 @@ function getInjectedParametersWithSourceCode(
315316
const { importSpecifier } =
316317
getImportDeclarationSpecifier(importDeclarations, importName) ?? {};
317318

319+
const injectImportDeclarations =
320+
getImportDeclarations(sourceCode.ast, '@angular/core') ?? [];
321+
322+
const { importSpecifier: injectImportSpecifier } =
323+
getImportDeclarationSpecifier(injectImportDeclarations, 'inject') ?? {};
324+
318325
if (!importSpecifier) {
319326
return { sourceCode };
320327
}
@@ -335,6 +342,19 @@ function getInjectedParametersWithSourceCode(
335342
return identifiers.concat(parent.parent.parent as InjectedParameter);
336343
}
337344

345+
if (
346+
parent &&
347+
isCallExpression(parent) &&
348+
isIdentifier(parent.callee) &&
349+
parent.callee.name == 'inject' &&
350+
parent.parent &&
351+
isPropertyDefinition(parent.parent) &&
352+
isIdentifier(parent.parent.key) &&
353+
injectImportSpecifier
354+
) {
355+
return identifiers.concat(parent.parent.key as InjectedParameter);
356+
}
357+
338358
return identifiers;
339359
}, []);
340360
return { identifiers, sourceCode };

0 commit comments

Comments
 (0)