diff --git a/package.json b/package.json index 212fd54..150b7f8 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "build:all": "npx nx run-many --target=build && chmod +x dist/packages/core/src/bin/main.js", "commit": "commit", "lint:all": "eslint ./packages", - "link:sheriff": "npm run build:all && yalc publish dist/packages/core && yalc publish dist/packages/eslint-plugin && yalc link @softarc/sheriff-core @softarc/eslint-plugin-sheriff", + "link:sheriff": "yarn run build:all && yalc publish dist/packages/core && yalc publish dist/packages/eslint-plugin && yalc link @softarc/sheriff-core @softarc/eslint-plugin-sheriff", "run:cli": "nx build core && chmod +x dist/packages/core/src/bin/main.js", "test": "vitest", "test:ci": "vitest -c vitest.config.ci.ts" diff --git a/packages/eslint-plugin/src/lib/rules/create-rule.ts b/packages/eslint-plugin/src/lib/rules/create-rule.ts index a8a5d6d..6e9d4d5 100644 --- a/packages/eslint-plugin/src/lib/rules/create-rule.ts +++ b/packages/eslint-plugin/src/lib/rules/create-rule.ts @@ -1,6 +1,8 @@ -import { Rule } from 'eslint'; -import {Executor, ExecutorNode} from './executor'; import { UserError } from '@softarc/sheriff-core'; +import { Rule } from 'eslint'; +import path from 'path'; +import { Executor, ExecutorNode } from './executor'; +import { FileFilter } from './file-filter'; /** * Factory function generating a rule that traverses @@ -15,15 +17,18 @@ import { UserError } from '@softarc/sheriff-core'; */ export const createRule: ( ruleName: string, + fileFilter: FileFilter, executor: Executor, -) => Rule.RuleModule = (ruleName, executor) => ({ +) => Rule.RuleModule = (ruleName, fileFilter, executor) => ({ create: (context) => { + const filename = context.filename ?? context.getFilename(); + if (isExcluded(fileFilter, filename)) { + return {}; + } + let isFirstRun = true; let hasInternalError = false; - const executeRuleWithContext = ( - node: ExecutorNode, - ) => { - const filename = context.filename ?? context.getFilename(); + const executeRuleWithContext = (node: ExecutorNode) => { const sourceCode = context.sourceCode?.text ?? context.getSourceCode().text; @@ -60,3 +65,11 @@ export const createRule: ( }; }, }); + +function isExcluded({ include, exclude }: FileFilter, filePath: string) { + const fileName = path.basename(filePath); + return ( + (include && !include.some((includeFile) => fileName === includeFile)) || + (exclude && exclude.some((excludeFile) => fileName === excludeFile)) + ); +} diff --git a/packages/eslint-plugin/src/lib/rules/deep-import.ts b/packages/eslint-plugin/src/lib/rules/deep-import.ts index 6e97878..eaf4108 100644 --- a/packages/eslint-plugin/src/lib/rules/deep-import.ts +++ b/packages/eslint-plugin/src/lib/rules/deep-import.ts @@ -1,8 +1,10 @@ import { violatesEncapsulationRule } from '@softarc/sheriff-core'; import { createRule } from './create-rule'; +import { excludeSheriffConfig } from './file-filter'; export const deepImport = createRule( 'Deep Import', + excludeSheriffConfig, (context, node, isFirstRun, filename, sourceCode) => { const importValue = (node.source as { value: string }).value; const message = violatesEncapsulationRule( @@ -10,7 +12,7 @@ export const deepImport = createRule( importValue, isFirstRun, sourceCode, - true + true, ); if (message) { context.report({ diff --git a/packages/eslint-plugin/src/lib/rules/dependency-rule.ts b/packages/eslint-plugin/src/lib/rules/dependency-rule.ts index d3a7acd..e241028 100644 --- a/packages/eslint-plugin/src/lib/rules/dependency-rule.ts +++ b/packages/eslint-plugin/src/lib/rules/dependency-rule.ts @@ -1,8 +1,10 @@ import { violatesDependencyRule } from '@softarc/sheriff-core'; import { createRule } from './create-rule'; +import { excludeSheriffConfig } from './file-filter'; export const dependencyRule = createRule( 'Dependency Rule', + excludeSheriffConfig, (context, node, isFirstRun, filename, sourceCode) => { const importValue = (node.source as { value: string }).value; const message = violatesDependencyRule( diff --git a/packages/eslint-plugin/src/lib/rules/encapsulation.ts b/packages/eslint-plugin/src/lib/rules/encapsulation.ts index ff0176e..5f59bda 100644 --- a/packages/eslint-plugin/src/lib/rules/encapsulation.ts +++ b/packages/eslint-plugin/src/lib/rules/encapsulation.ts @@ -1,8 +1,10 @@ import { violatesEncapsulationRule } from '@softarc/sheriff-core'; import { createRule } from './create-rule'; +import { excludeSheriffConfig } from './file-filter'; export const encapsulation = createRule( 'Encapsulation', + excludeSheriffConfig, (context, node, isFirstRun, filename, sourceCode) => { const importValue = (node.source as { value: string }).value; const message = violatesEncapsulationRule( @@ -10,7 +12,7 @@ export const encapsulation = createRule( importValue, isFirstRun, sourceCode, - false + false, ); if (message) { context.report({ diff --git a/packages/eslint-plugin/src/lib/rules/file-filter.ts b/packages/eslint-plugin/src/lib/rules/file-filter.ts new file mode 100644 index 0000000..4bb3114 --- /dev/null +++ b/packages/eslint-plugin/src/lib/rules/file-filter.ts @@ -0,0 +1,14 @@ +export interface FileFilter { + include?: string[]; + exclude?: string[]; +} + +export const sheriffConfigFileName = 'sheriff.config.ts'; + +export const excludeSheriffConfig: FileFilter = { + exclude: [sheriffConfigFileName], +}; + +export const onlySheriffConfig: FileFilter = { + include: [sheriffConfigFileName], +}; diff --git a/packages/eslint-plugin/src/lib/rules/tests/create-rule.spec.ts b/packages/eslint-plugin/src/lib/rules/tests/create-rule.spec.ts index d139910..377ec4a 100644 --- a/packages/eslint-plugin/src/lib/rules/tests/create-rule.spec.ts +++ b/packages/eslint-plugin/src/lib/rules/tests/create-rule.spec.ts @@ -1,17 +1,18 @@ +import { UserError } from '@softarc/sheriff-core'; import { RuleTester } from 'eslint'; +import { parser } from 'typescript-eslint'; import { afterEach, describe, expect, it, vitest } from 'vitest'; import { createRule } from '../create-rule'; -import { UserError } from '@softarc/sheriff-core'; -import { parser } from 'typescript-eslint'; +import { excludeSheriffConfig, sheriffConfigFileName } from '../file-filter'; const tester = new RuleTester({ - languageOptions: { parser, sourceType: 'module' } + languageOptions: { parser, sourceType: 'module' }, }); const ruleExecutor = { foo: () => void true }; const spy = vitest.spyOn(ruleExecutor, 'foo'); -export const testRule = createRule('Test Rule', () => { +export const testRule = createRule('Test Rule', excludeSheriffConfig, () => { ruleExecutor.foo(); }); @@ -34,6 +35,21 @@ describe('create rule', () => { expect(spy).toHaveBeenCalledTimes(2); }); + it('should NOT call the rule executor for any import or export types when filename is "sheriff.config.ts"', () => { + tester.run('test-rule', testRule, { + valid: [ + { + filename: sheriffConfigFileName, + code: `import {AppComponent} from './app.component' + const a = new AppComponent(); + import('../util.ts')`, + }, + ], + invalid: [], + }); + expect(spy).toHaveBeenCalledTimes(0); + }); + for (const { throwing, message } of [ { throwing: new Error('Test Error'), @@ -84,7 +100,7 @@ describe('create rule', () => { `, }, ], - invalid: [] + invalid: [], }); expect(spy).toHaveBeenCalledTimes(2); diff --git a/tsconfig.spec.json b/tsconfig.spec.json index 20984f2..83dc89a 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -1,5 +1,4 @@ { "extends": "./tsconfig.base.json", "include": ["**/*.spec.ts"] - ] }