Skip to content
This repository has been archived by the owner on May 23, 2021. It is now read-only.

Commit

Permalink
feat: add ngrx-no-effects-in-providers (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
timdeschryver authored Jan 9, 2020
1 parent fb2137c commit 39f735a
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ To enable all rules, use the `recommended` configuration file.
| ngrx-no-dispatch-in-effects | An Effect should not call `store.dispatch`, but should return an action | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-dispatch-in-effects/fixture.ts.lint) |
| ngrx-no-duplicate-action-types | An action type must be unique | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-duplicate-action-types/fixture.ts.lint) |
| ngrx-no-effect-decorator | The createEffect creator function is preferred | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-effect-decorator/fixture.ts.lint) |
| ngrx-no-effects-in-providers | The Effect should not be listed as a provider if it is added to the EffectsModule | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-effects-in-providers/fixture.ts.lint) |
| ngrx-no-multiple-actions-in-effects | An Effect should not return multiple actions | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-multiple-actions-in-effects/fixture.ts.lint) |
| ngrx-no-multiple-stores | Store should at most be one time injected | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-multiple-stores/fixture.ts.lint) |
| ngrx-no-reducer-in-key-names | Avoid the word "reducer" in the key names | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-reducer-in-key-names/fixture.ts.lint) |
Expand Down
3 changes: 3 additions & 0 deletions src/recommended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ module.exports = {
'ngrx-no-effect-decorator': {
severity: 'warning',
},
'ngrx-no-effects-in-providers': {
severity: 'error',
},
'ngrx-no-multiple-actions-in-effects': {
severity: 'warning',
},
Expand Down
49 changes: 49 additions & 0 deletions src/rules/ngrxNoEffectsInProvidersRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { tsquery } from '@phenomnomnominal/tsquery'
import * as Lint from 'tslint'
import * as ts from 'typescript'
import { NG_MODULE_IMPORTS, NG_MODULE_PROVIDERS } from '../utils/queries'

export class Rule extends Lint.Rules.TypedRule {
public static metadata: Lint.IRuleMetadata = {
description: 'The Effect should not be listed as a provider',
descriptionDetails:
'If an Effect is registered to the EffectsModule and is added as a provider, it will be registered twice',
options: null,
optionsDescription: 'Not configurable',
requiresTypeInfo: false,
ruleName: 'ngrx-no-effects-in-providers',
type: 'functionality',
typescriptOnly: true,
}

public static FAILURE_STRING =
'The Effect should not be listed as a provider if it is added to the EffectsModule'

private static QUERY = `${NG_MODULE_IMPORTS} > CallExpression[expression.expression.text="EffectsModule"][expression.name.text=/forFeature|forRoot/] > ArrayLiteralExpression > Identifier`

public applyWithProgram(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const effectIdentifierNodes = tsquery(
sourceFile,
Rule.QUERY,
) as ts.Identifier[]

const effectNames = effectIdentifierNodes.map(node => node.text).join('|')
const hits = tsquery(
sourceFile,
`${NG_MODULE_PROVIDERS} > Identifier[name=/${effectNames}/]`,
)

const failures = hits.map(
(node): Lint.RuleFailure =>
new Lint.RuleFailure(
sourceFile,
node.getStart(),
node.getStart() + node.getWidth(),
Rule.FAILURE_STRING,
this.ruleName,
),
)

return failures
}
}
7 changes: 7 additions & 0 deletions src/utils/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const queryNgModuleProperty = (property: string) =>
`${NG_MODULE_QUERY} > ObjectLiteralExpression PropertyAssignment[name.text="${property}"] > ArrayLiteralExpression`

export const NG_MODULE_QUERY =
'ClassDeclaration > Decorator > CallExpression[expression.text="NgModule"]'
export const NG_MODULE_IMPORTS = queryNgModuleProperty('imports')
export const NG_MODULE_PROVIDERS = queryNgModuleProperty('providers')
21 changes: 21 additions & 0 deletions test/rules/ngrx-no-effects-in-providers/fixture.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import { StoreModule } from '@ngrx/store'
import { EffectsModule } from '@ngrx/effects'

@NgModule({
imports: [
StoreModule.forFeature('persons', {"foo": "bar"}),
EffectsModule.forRoot([RootEffectOne, RootEffectTwo]),
EffectsModule.forFeature([FeatEffectOne, FeatEffectTwo]),
EffectsModule.forFeature([FeatEffectThree]),
],
providers: [FeatEffectTwo, UnRegisteredEffect, FeatEffectThree, RootEffectTwo],
~~~~~~~~~~~~~ [error]
~~~~~~~~~~~~~~~ [error]
~~~~~~~~~~~~~ [error]

bootstrap: [AppComponent],
})
export class AppModule {}

[error]: The Effect should not be listed as a provider if it is added to the EffectsModule
12 changes: 12 additions & 0 deletions test/rules/ngrx-no-effects-in-providers/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"baseUrl": ".",
"lib": ["es2015"],
"noEmit": true,
"paths": {
"@ngrx/effects": ["../../../node_modules/@ngrx/effects"]
},
"skipLibCheck": true,
"target": "es5"
}
}
7 changes: 7 additions & 0 deletions test/rules/ngrx-no-effects-in-providers/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"defaultSeverity": "error",
"rules": {
"ngrx-no-effects-in-providers": true
},
"rulesDirectory": ["../../../dist/rules"]
}

0 comments on commit 39f735a

Please sign in to comment.