From 8ac9f478ec42460ef8bef78e267db348438a425d Mon Sep 17 00:00:00 2001 From: Romain Racamier-Lafon Date: Sat, 23 Dec 2023 15:10:34 +0100 Subject: [PATCH] add no-restricted-syntax to prevent class uses --- .eslintrc.json | 7 ++++++ README.md | 2 +- src/constants.ts | 1 + src/file.ts | 1 + src/files/dependency-cruiser.ts | 1 + src/files/editor-config.ts | 1 + src/files/eslint.file.ts | 1 + src/files/gh-workflow.ts | 1 + src/files/git.ts | 1 + src/files/license.ts | 1 + src/files/npmrc.file.ts | 1 + src/files/nvmrc.ts | 1 + src/files/nycrc.ts | 1 + src/files/package.file.ts | 1 + src/files/readme.ts | 3 +++ src/files/renovate.ts | 1 + src/files/repo-checker.ts | 1 + src/files/tailwind.ts | 1 + src/files/travis.ts | 1 + src/files/ts-config.ts | 1 + src/logger.ts | 1 + tests/__snapshots__/check.test.ts.snap | 4 +-- tests/file.test.ts | 9 +++++++ tests/files/__snapshots__/eslint.test.ts.snap | 25 ++++++++++++------- 24 files changed, 56 insertions(+), 12 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index d5c13f43..321a05fd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -139,6 +139,13 @@ "max-statements-per-line": "off", "no-console": "error", "no-inline-comments": "off", + "no-restricted-syntax": [ + "error", + { + "message": "Avoid using Class, just use good old unit-testable functions :)", + "selector": "ClassDeclaration" + } + ], "object-curly-spacing": [ "error", "always" diff --git a/README.md b/README.md index 288178b7..2a2d758d 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ If file already exists, use `--force` to overwrite it. - [ ] check last tag, suggest to tag if last one is old - [ ] extends unit tests to src/files (remove `c8 ignore start` temporary exclusions) - [ ] prepare a json schema for .repo-checker.json -- [ ] check vitest config file +- [ ] try to avoid using class in this project and remove `eslint-disable-next-line no-restricted-syntax` ## Benchmarks diff --git a/src/constants.ts b/src/constants.ts index 0373288b..b1de70f8 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -9,6 +9,7 @@ export const dataFileName = '.repo-checker.json' export const repoCheckerPath = path.join(__dirname, '..') export const templatePath = path.join(repoCheckerPath, 'templates') +// eslint-disable-next-line no-restricted-syntax export class ProjectData { /** diff --git a/src/file.ts b/src/file.ts index c63327bd..3a1d5a8b 100644 --- a/src/file.ts +++ b/src/file.ts @@ -5,6 +5,7 @@ import { fileExists, getFileSizeInKo, join, messageToCode, readFileInFolder, rea const defaultAmount = 99 +// eslint-disable-next-line no-restricted-syntax export class FileBase { public passed: string[] = [] diff --git a/src/files/dependency-cruiser.ts b/src/files/dependency-cruiser.ts index 235c07ae..2803f9cc 100644 --- a/src/files/dependency-cruiser.ts +++ b/src/files/dependency-cruiser.ts @@ -1,5 +1,6 @@ import { FileBase } from '../file' +// eslint-disable-next-line no-restricted-syntax export class DependencyCruiserFile extends FileBase { public async start (): Promise { const isUsingDepCruiser = this.test(this.data.isUsingDependencyCruiser, 'use dependency cruiser', true) diff --git a/src/files/editor-config.ts b/src/files/editor-config.ts index c8d6a311..db3b7376 100644 --- a/src/files/editor-config.ts +++ b/src/files/editor-config.ts @@ -1,5 +1,6 @@ import { FileBase } from '../file' +// eslint-disable-next-line no-restricted-syntax export class EditorConfigFile extends FileBase { public async start (): Promise { const hasFile = await this.checkFileExists('.editorconfig') diff --git a/src/files/eslint.file.ts b/src/files/eslint.file.ts index 11b34dee..a3955342 100644 --- a/src/files/eslint.file.ts +++ b/src/files/eslint.file.ts @@ -5,6 +5,7 @@ import { log } from '../logger' import { objectToJson, readFileInFolder } from '../utils' import { recommendedVueRules, specificRepoCheckerRules, type EslintConfigRules, type EslintRcJsonFile } from './eslint.model' +// eslint-disable-next-line no-restricted-syntax export class EsLintFile extends FileBase { private checkExtends () { diff --git a/src/files/gh-workflow.ts b/src/files/gh-workflow.ts index 2e748a89..270686df 100644 --- a/src/files/gh-workflow.ts +++ b/src/files/gh-workflow.ts @@ -1,6 +1,7 @@ import { FileBase } from '../file' /* c8 ignore start */ +// eslint-disable-next-line no-restricted-syntax export class GithubWorkflowFile extends FileBase { private checkPnpm (): void { diff --git a/src/files/git.ts b/src/files/git.ts index c6402922..046afd5e 100644 --- a/src/files/git.ts +++ b/src/files/git.ts @@ -1,5 +1,6 @@ import { FileBase } from '../file' +// eslint-disable-next-line no-restricted-syntax export class GitFile extends FileBase { public async start (): Promise { this.test(!this.data.hasMainBranch, 'avoid "main" branch reference, use master instead & git bclean', true) diff --git a/src/files/license.ts b/src/files/license.ts index 6bdc33dc..b8e9f9ba 100644 --- a/src/files/license.ts +++ b/src/files/license.ts @@ -1,6 +1,7 @@ import { FileBase } from '../file' /* c8 ignore start */ +// eslint-disable-next-line no-restricted-syntax export class LicenseFile extends FileBase { public async start (): Promise { const hasFile = await this.checkFileExists('LICENSE') diff --git a/src/files/npmrc.file.ts b/src/files/npmrc.file.ts index f963d2f3..785037a2 100644 --- a/src/files/npmrc.file.ts +++ b/src/files/npmrc.file.ts @@ -1,5 +1,6 @@ import { FileBase } from '../file' +// eslint-disable-next-line no-restricted-syntax export class NpmRcFile extends FileBase { private checkPrePost () { diff --git a/src/files/nvmrc.ts b/src/files/nvmrc.ts index 528a20d0..98fbffe8 100644 --- a/src/files/nvmrc.ts +++ b/src/files/nvmrc.ts @@ -1,6 +1,7 @@ import { FileBase } from '../file' /* c8 ignore start */ +// eslint-disable-next-line no-restricted-syntax export class NvmrcFile extends FileBase { public async start (): Promise { const hasFile = await this.checkFileExists('.nvmrc') diff --git a/src/files/nycrc.ts b/src/files/nycrc.ts index 5865bb1e..e465f86c 100644 --- a/src/files/nycrc.ts +++ b/src/files/nycrc.ts @@ -1,6 +1,7 @@ import { FileBase } from '../file' import { log } from '../logger' +// eslint-disable-next-line no-restricted-syntax export class NycRcFile extends FileBase { private async getConfigFileName (): Promise { diff --git a/src/files/package.file.ts b/src/files/package.file.ts index aabbbc3d..ce48499e 100644 --- a/src/files/package.file.ts +++ b/src/files/package.file.ts @@ -5,6 +5,7 @@ import { FileBase } from '../file' import { log } from '../logger' import { findInFolder, join } from '../utils' +// eslint-disable-next-line no-restricted-syntax export class PackageJsonFile extends FileBase { // eslint-disable-next-line max-statements diff --git a/src/files/readme.ts b/src/files/readme.ts index 8353ce8f..e2280caa 100644 --- a/src/files/readme.ts +++ b/src/files/readme.ts @@ -7,6 +7,7 @@ import { FileBase } from '../file' import { log } from '../logger' import { fileExists, join, readFile } from '../utils' +// eslint-disable-next-line no-restricted-syntax class Thanks { public markdown = '' @@ -16,6 +17,7 @@ class Thanks { } } +// eslint-disable-next-line no-restricted-syntax class Badge { public markdown = '' @@ -33,6 +35,7 @@ const deprecatedBadges = [ ] /* c8 ignore start */ +// eslint-disable-next-line no-restricted-syntax export class ReadmeFile extends FileBase { private checkMarkdown (): void { let hasNoCrLf = this.shouldContains('no CRLF Windows carriage return', /\r/u, 0, false, 'prefer Unix LF', true) diff --git a/src/files/renovate.ts b/src/files/renovate.ts index ee88b14e..b4640138 100644 --- a/src/files/renovate.ts +++ b/src/files/renovate.ts @@ -1,6 +1,7 @@ import { FileBase } from '../file' /* c8 ignore start */ +// eslint-disable-next-line no-restricted-syntax export class RenovateFile extends FileBase { public async start (): Promise { const hasFile = await this.checkFileExists('renovate.json', true) diff --git a/src/files/repo-checker.ts b/src/files/repo-checker.ts index 074a093c..19473535 100644 --- a/src/files/repo-checker.ts +++ b/src/files/repo-checker.ts @@ -2,6 +2,7 @@ import { dataFileName } from '../constants' import { FileBase } from '../file' import { deleteFile, join, jsToJson, readFileInFolder, writeFile } from '../utils' +// eslint-disable-next-line no-restricted-syntax export class RepoCheckerConfigFile extends FileBase { public async start (): Promise { await this.migrateOldConfig('.repo-checker.js') diff --git a/src/files/tailwind.ts b/src/files/tailwind.ts index 939598e8..c739f0b5 100644 --- a/src/files/tailwind.ts +++ b/src/files/tailwind.ts @@ -1,5 +1,6 @@ import { FileBase } from '../file' +// eslint-disable-next-line no-restricted-syntax export class TailwindFile extends FileBase { public async start (): Promise { if (!this.data.isUsingTailwind) return diff --git a/src/files/travis.ts b/src/files/travis.ts index 8c0055d6..1f4e49f4 100644 --- a/src/files/travis.ts +++ b/src/files/travis.ts @@ -1,6 +1,7 @@ import { FileBase } from '../file' /* c8 ignore start */ +// eslint-disable-next-line no-restricted-syntax export class TravisFile extends FileBase { public async start (): Promise { const hasFile = await this.fileExists('.travis.yml') diff --git a/src/files/ts-config.ts b/src/files/ts-config.ts index 1f6f8e9c..a6e4dd57 100644 --- a/src/files/ts-config.ts +++ b/src/files/ts-config.ts @@ -33,6 +33,7 @@ interface TsConfigJsonFile { include: string[] } +// eslint-disable-next-line no-restricted-syntax export class TsConfigFile extends FileBase { private fileContentObject: TsConfigJsonFile | undefined diff --git a/src/logger.ts b/src/logger.ts index 5b5b7f5e..042b45a0 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,5 +1,6 @@ import { bgBlue, black, Logger } from 'shuutils' +// eslint-disable-next-line no-restricted-syntax class ExtendedLogger extends Logger { public fix (...stuff: readonly string[]): void { const items = Array.from(stuff) diff --git a/tests/__snapshots__/check.test.ts.snap b/tests/__snapshots__/check.test.ts.snap index 684def90..ee316214 100644 --- a/tests/__snapshots__/check.test.ts.snap +++ b/tests/__snapshots__/check.test.ts.snap @@ -228,7 +228,7 @@ exports[`check C data/tsProject 1`] = ` "warnings": [ "use-dependency-cruiser", "eslintrc-json-could-have-unicorn-rules-extend-plugin-unicorn-all", - "eslintrc-json-current-eslintrc-json-has-only-1-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "eslintrc-json-current-eslintrc-json-has-only-1-of-the-66-custom-rules-in-repo-checker-eslintrc-json", "has-a-npmrc-file", "package-json-main-file-maximum-size-is-specified-in-data-file-ex-max-size-ko-100", "package-json-could-have-a-schema-declaration-like-schema-https-json-schemastore-org-package-43m30m-fixable-39m49m", @@ -333,7 +333,7 @@ exports[`check E data folders and not throw 1`] = ` "warnings": [ "use-dependency-cruiser", "eslintrc-json-could-have-unicorn-rules-extend-plugin-unicorn-all", - "eslintrc-json-current-eslintrc-json-has-only-1-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "eslintrc-json-current-eslintrc-json-has-only-1-of-the-66-custom-rules-in-repo-checker-eslintrc-json", "has-a-npmrc-file", "package-json-main-file-maximum-size-is-specified-in-data-file-ex-max-size-ko-100", "package-json-could-have-a-schema-declaration-like-schema-https-json-schemastore-org-package-43m30m-fixable-39m49m", diff --git a/tests/file.test.ts b/tests/file.test.ts index 46a87dc0..1d3aef6b 100644 --- a/tests/file.test.ts +++ b/tests/file.test.ts @@ -12,6 +12,7 @@ const missingFilepath = join(repoCheckerPath, missingFilename) const fakeContent = 'zorglub' it('file A simple validator', async () => { + // eslint-disable-next-line no-restricted-syntax class MyFile extends FileBase { public async start (): Promise { await writeFile(missingFilepath, 'Foobar content') @@ -38,6 +39,7 @@ it('file A simple validator', async () => { }) it('file B validator with fix', async () => { + // eslint-disable-next-line no-restricted-syntax class MyFileFix extends FileBase { public async start (): Promise { await this.checkFileExists(existingFilename) @@ -55,6 +57,7 @@ it('file B validator with fix', async () => { }) it('file C validator with fix & force, overwrite a problematic file with template', async () => { + // eslint-disable-next-line no-restricted-syntax class MyFileFixForce extends FileBase { public async start (): Promise { await this.inspectFile(existingFilename) @@ -73,6 +76,7 @@ it('file C validator with fix & force, overwrite a problematic file with templat it('file D validator with fix & force, update a problematic file on the go', async () => { let originalContent = '' + // eslint-disable-next-line no-restricted-syntax class MyFileFixForce extends FileBase { public async start (): Promise { await this.inspectFile(existingFilename) @@ -90,6 +94,7 @@ it('file D validator with fix & force, update a problematic file on the go', asy it('file E validator without force cannot fix a problematic file on the go', async () => { let originalContent = '' + // eslint-disable-next-line no-restricted-syntax class MyFileFixForce extends FileBase { public async start (): Promise { await this.inspectFile(existingFilename) @@ -106,6 +111,7 @@ it('file E validator without force cannot fix a problematic file on the go', asy }) it('file F validator with fix cannot fix if the template require data that is missing', async () => { + // eslint-disable-next-line no-restricted-syntax class MyFileFix extends FileBase { public async start (): Promise { await this.checkFileExists('template-example.json') @@ -118,6 +124,7 @@ it('file F validator with fix cannot fix if the template require data that is mi }) it('file G validator can detect a missing schema', async () => { + // eslint-disable-next-line no-restricted-syntax class MyFileFix extends FileBase { public async start (): Promise { await sleep(1) @@ -132,6 +139,7 @@ it('file G validator can detect a missing schema', async () => { }) it('file H validator can detect an existing schema', async () => { + // eslint-disable-next-line no-restricted-syntax class MyFileFix extends FileBase { public async start (): Promise { await sleep(1) @@ -150,6 +158,7 @@ it('file H validator can detect an existing schema', async () => { }) it('file I validator can fix a missing schema', async () => { + // eslint-disable-next-line no-restricted-syntax class MyFileFix extends FileBase { public async start (): Promise { await sleep(1) diff --git a/tests/files/__snapshots__/eslint.test.ts.snap b/tests/files/__snapshots__/eslint.test.ts.snap index 92feb58f..1d3ed11a 100644 --- a/tests/files/__snapshots__/eslint.test.ts.snap +++ b/tests/files/__snapshots__/eslint.test.ts.snap @@ -90,7 +90,7 @@ exports[`eslint B config file empty 1`] = ` "could-have-hardcore-rules-extend-hardcore", "could-have-eslint-recommended-rules-extend-eslint-recommended", "could-have-unicorn-rules-extend-plugin-unicorn-all", - "current-eslintrc-json-has-only-16-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "current-eslintrc-json-has-only-16-of-the-66-custom-rules-in-repo-checker-eslintrc-json", ], } `; @@ -142,7 +142,7 @@ exports[`eslint C config file empty for ts project 1`] = ` "could-have-hardcore-rules-extend-hardcore", "could-have-eslint-recommended-rules-extend-eslint-recommended", "could-have-unicorn-rules-extend-plugin-unicorn-all", - "current-eslintrc-json-has-only-0-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "current-eslintrc-json-has-only-0-of-the-66-custom-rules-in-repo-checker-eslintrc-json", "could-have-hardcore-typescript-rules-extend-hardcore-ts", ], } @@ -196,7 +196,7 @@ exports[`eslint D config file empty for vue ts project 1`] = ` "could-have-hardcore-rules-extend-hardcore", "could-have-eslint-recommended-rules-extend-eslint-recommended", "could-have-unicorn-rules-extend-plugin-unicorn-all", - "current-eslintrc-json-has-only-0-of-the-72-custom-rules-in-repo-checker-eslintrc-json", + "current-eslintrc-json-has-only-0-of-the-73-custom-rules-in-repo-checker-eslintrc-json", "could-have-hardcore-typescript-rules-extend-hardcore-ts", ], } @@ -249,7 +249,7 @@ exports[`eslint E config file empty for tailwind project 1`] = ` "could-have-hardcore-rules-extend-hardcore", "could-have-eslint-recommended-rules-extend-eslint-recommended", "could-have-unicorn-rules-extend-plugin-unicorn-all", - "current-eslintrc-json-has-only-16-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "current-eslintrc-json-has-only-16-of-the-66-custom-rules-in-repo-checker-eslintrc-json", ], } `; @@ -309,7 +309,7 @@ exports[`eslint F config partial file for js project 1`] = ` "warnings": [ "could-have-hardcore-rules-extend-hardcore", "could-have-unicorn-rules-extend-plugin-unicorn-all", - "current-eslintrc-json-has-only-16-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "current-eslintrc-json-has-only-16-of-the-66-custom-rules-in-repo-checker-eslintrc-json", ], } `; @@ -368,7 +368,7 @@ exports[`eslint G config partial file for ts project 1`] = ` "warnings": [ "could-have-hardcore-rules-extend-hardcore", "could-have-unicorn-rules-extend-plugin-unicorn-all", - "current-eslintrc-json-has-only-0-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "current-eslintrc-json-has-only-0-of-the-66-custom-rules-in-repo-checker-eslintrc-json", "could-have-hardcore-typescript-rules-extend-hardcore-ts", ], } @@ -440,7 +440,7 @@ exports[`eslint H config partial file for vue ts project 1`] = ` "warnings": [ "could-have-hardcore-rules-extend-hardcore", "could-have-unicorn-rules-extend-plugin-unicorn-all", - "current-eslintrc-json-has-only-0-of-the-72-custom-rules-in-repo-checker-eslintrc-json", + "current-eslintrc-json-has-only-0-of-the-73-custom-rules-in-repo-checker-eslintrc-json", "could-have-hardcore-typescript-rules-extend-hardcore-ts", ], } @@ -578,7 +578,7 @@ exports[`eslint J config file with no rules 1`] = ` ], "warnings": [ "eslintrc-json-could-have-unicorn-rules-extend-plugin-unicorn-all", - "eslintrc-json-current-eslintrc-json-has-only-16-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "eslintrc-json-current-eslintrc-json-has-only-16-of-the-66-custom-rules-in-repo-checker-eslintrc-json", ], } `; @@ -654,7 +654,7 @@ exports[`eslint K config file with just rules (no override) 1`] = ` ], "warnings": [ "eslintrc-json-could-have-unicorn-rules-extend-plugin-unicorn-all", - "eslintrc-json-current-eslintrc-json-has-only-17-of-the-65-custom-rules-in-repo-checker-eslintrc-json", + "eslintrc-json-current-eslintrc-json-has-only-17-of-the-66-custom-rules-in-repo-checker-eslintrc-json", ], } `; @@ -878,6 +878,13 @@ exports[`eslint M fix rules in overrides 1`] = ` "max-statements-per-line": "off", "no-console": "error", "no-inline-comments": "off", + "no-restricted-syntax": [ + "error", + { + "message": "Avoid using Class, just use good old unit-testable functions :)", + "selector": "ClassDeclaration" + } + ], "object-curly-spacing": [ "error", "always"