diff --git a/.jest-eslint.config.js b/.jest-eslint.config.js index e0daf7d34d..300ad06187 100644 --- a/.jest-eslint.config.js +++ b/.jest-eslint.config.js @@ -5,8 +5,7 @@ module.exports = { displayName: 'lint', rootDir: __dirname, verbose: false, - reporters: ['@adeira/eslint-runner/reporter'], - runner: '@adeira/eslint-runner', + runner: 'jest-runner-eslint', testMatch: ['/src/**/*.js', '/scripts/**/*.js'], testPathIgnorePatterns: [ '/node_modules/', diff --git a/package.json b/package.json index d1c82960a6..9f36632856 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "devDependencies": { "@adeira/babel-preset-adeira": "^3.0.0", "@adeira/eslint-config": "^5.3.0", - "@adeira/eslint-runner": "^2.0.0", "@babel/cli": "^7.13.14", "@babel/core": "^7.13.14", "babel-eslint": "^10.1.0", @@ -20,7 +19,8 @@ "eslint": "^7.23.0", "flow-bin": "^0.148.0", "glob": "^7.1.6", - "jest": "^26.6.3" + "jest": "^26.6.3", + "jest-runner-eslint": "^0.10.0" }, "jest": { "testRegex": "/scripts/jest/dontRunJestDirectly\\.js$" @@ -29,9 +29,15 @@ "//": [ "Please do not add new scripts here. Use scripts section in your workspace instead." ], - "lint": "yarn run eslint-config-prettier src/js/src/invariant.js && yarn run prettier --check \"src/**/*.md\" && yarn run jest --config=.jest-eslint.config.js", + "lint": "yarn run eslint-config-prettier src/js/src/invariant.js && yarn run prettier --check \"src/**/*.md\" && yarn run jest --config=.jest-eslint.config.js --changedSince=origin/master^", "scanner": "yarn run jest --config src/monorepo-scanner/.jest.config.js", "test": "yarn run flow && yarn run lint && yarn run test-only --ci --colors && yarn run scanner", "test-only": "src/monorepo-utils/bin/monorepo-run-tests.js" + }, + "jest-runner-eslint": { + "cliOptions": { + "format": "codeframe", + "reportUnusedDisableDirectives": true + } } } diff --git a/scripts/publishedPackages.json b/scripts/publishedPackages.json index f5cea35b5c..0deaa3296a 100644 --- a/scripts/publishedPackages.json +++ b/scripts/publishedPackages.json @@ -4,7 +4,6 @@ "@adeira/css-colors", "@adeira/eslint-config", "@adeira/eslint-fixtures-tester", - "@adeira/eslint-runner", "@adeira/fetch", "@adeira/fixtures-tester", "@adeira/flow-config-parser", diff --git a/src/eslint-config-adeira/README.md b/src/eslint-config-adeira/README.md index 81740c513a..738d920afa 100644 --- a/src/eslint-config-adeira/README.md +++ b/src/eslint-config-adeira/README.md @@ -54,31 +54,6 @@ It is important to report any issues with the eslint configuration back so we ca Also please note that **you should not ignore Eslint warnings**! These warnings are helping you to migrate to the future major version. Some of them will turn into errors in the next major version bump. -# Custom Eslint Runner - -Custom Eslint Runner was moved to a different package so you can use it independently, see: [@adeira/eslint-runner](https://github.com/adeira/universe/tree/master/src/eslint-runner) - -## Tip - -You can benefit from the main Jest executor much more. You can for example use watch mode to watch changes in one directory: - -```text -yarn run lint src/packages/relay --watch [--all] -``` - -Basically, every Jest watch option is available: - -```text -Watch Usage - › Press a to run all tests. - › Press f to run only failed tests. - › Press o to only run tests related to changed files. - › Press p to filter by a filename regex pattern. - › Press t to filter by a test name regex pattern. - › Press q to quit watch mode. - › Press Enter to trigger a test run. -``` - # Prior art - https://github.com/facebook/fbjs diff --git a/src/eslint-config-adeira/package.json b/src/eslint-config-adeira/package.json index 808039aa5c..b815a5994c 100644 --- a/src/eslint-config-adeira/package.json +++ b/src/eslint-config-adeira/package.json @@ -33,8 +33,5 @@ }, "peerDependencies": { "eslint": ">=7.14.0" - }, - "optionalDependencies": { - "@adeira/eslint-runner": "^2.0.0" } } diff --git a/src/eslint-runner/.npmignore b/src/eslint-runner/.npmignore deleted file mode 100644 index 1d2c8b25f0..0000000000 --- a/src/eslint-runner/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -__tests__ -BUILD.bazel -BUILD diff --git a/src/eslint-runner/BUILD.bazel b/src/eslint-runner/BUILD.bazel deleted file mode 100644 index 51f70846e9..0000000000 --- a/src/eslint-runner/BUILD.bazel +++ /dev/null @@ -1,11 +0,0 @@ -load("//:bazel/macros/build_yarn_workspace.bzl", "build_yarn_workspace") -load("//:bazel/macros/test_yarn_workspace.bzl", "test_yarn_workspace") - -build_yarn_workspace( - name = "eslint_runner", - package_name = "@adeira/eslint-runner", -) - -test_yarn_workspace( - name = "test", -) diff --git a/src/eslint-runner/CHANGELOG.md b/src/eslint-runner/CHANGELOG.md deleted file mode 100644 index a9cfecd2f3..0000000000 --- a/src/eslint-runner/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# Unreleased - -# 2.0.0 - -Support for Node.js 12 has been removed. This package might continue working on older Node.js versions, however, it's highly recommended upgrading to Node.js version 14 or newer. For more details, see: https://nodejs.org/en/about/releases/, or discuss here: https://github.com/adeira/universe/discussions/1588 - -# 1.0.0 - -Initial stable release. diff --git a/src/eslint-runner/LICENSE b/src/eslint-runner/LICENSE deleted file mode 100644 index 3b9565ef58..0000000000 --- a/src/eslint-runner/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019-present, Adeira - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/src/eslint-runner/README.md b/src/eslint-runner/README.md deleted file mode 100644 index 7ce47acdb7..0000000000 --- a/src/eslint-runner/README.md +++ /dev/null @@ -1,50 +0,0 @@ -Eslint runner for large projects - **faster than Eslint** itself. 🤯 - -``` -yarn add jest @adeira/eslint-runner --dev -``` - -This package contains a special runner for Jest to speedup Eslint checks. It executes Eslint in parallel thanks to Jest workers so it's much faster when you have many files with complicated rules. You have to create special Jest config in order to use this runner (`.jest-eslint.config.js`): - -```js -module.exports = { - displayName: 'lint', - rootDir: __dirname, - verbose: false, - reporters: [ - // optional but quite nice, give it a try - '@adeira/eslint-runner/reporter', - ], - runner: '@adeira/eslint-runner', - testMatch: [ - // add whatever files you want to lint - '/src/**/*.js', - '/scripts/**/*.js', - ], -}; -``` - -It is of course possible to run this lint as yet another Jest project (using `options.projects` configuration). To execute this runner you have to call Jest like this: - -```json -{ - "scripts": { - "lint": "yarn jest --config=.jest-eslint.config.js" - } -} -``` - -It tries to detect files to lint because it's highly inefficient to test all the files everytime. However, you can do so by using `--all` flag like so: `yarn run lint --all`. - -This Eslint runner not only runs all the lints much faster, but it also performs automatic fixes. Automatic fixes are performed only while developing locally, not during CI. You can disable this behavior even locally by setting `CI=true` environment variable. - -You can also suppress warnings in report by `--no-warnings` option. Usage of this option is generally discouraged, although it may be handy in certain scenarios - consider migration strategy to adopt a new rule on the legacy project when you get hundreds of reports: - -1. You set severity to `error` for given rule in `eslintrc` file. -1. In every legacy file where rule is broken, you lower the severity to `warn`, e.g. by adding `/* eslint flowtype/no-weak-types: "warn" */` comment to the top of file or in `eslintrc` for specific subdirectory where rule is too much broken. -1. As warnings are turned on by default, all contributors to the project can see ongoing issues in files changed by them so they can easily fix problems on that part of codebase, helping with migration and eventually reducing no. of issues to zero. -1. When all files are checked or there are too many changes, it might be difficult to locate an error in long report full of warnings. This is the special case when it's handy to rerun the check with `--no-warnings` option to locate the issue. - -And it has a nice and helpful output: - -![codeframe output](./codeframe-output.png) diff --git a/src/eslint-runner/codeframe-output.png b/src/eslint-runner/codeframe-output.png deleted file mode 100644 index 88cc451b7f..0000000000 Binary files a/src/eslint-runner/codeframe-output.png and /dev/null differ diff --git a/src/eslint-runner/index.js b/src/eslint-runner/index.js deleted file mode 100644 index 34d74f4d95..0000000000 --- a/src/eslint-runner/index.js +++ /dev/null @@ -1,18 +0,0 @@ -// @flow - -const { createJestRunner } = require('create-jest-runner'); - -const verifyPackageTree = require('./src/verifyPackageTree'); - -const externalConfig = process.argv.slice(2); - -verifyPackageTree(); - -module.exports = (createJestRunner(require.resolve('./src/run'), { - getExtraOptions: () => { - return { - runAll: externalConfig.includes('--all'), - noWarnings: externalConfig.includes('--no-warnings'), - }; - }, -}) /*: any */); diff --git a/src/eslint-runner/package.json b/src/eslint-runner/package.json deleted file mode 100644 index 56d99b17cd..0000000000 --- a/src/eslint-runner/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@adeira/eslint-runner", - "description": "Eslint runner for large projects - faster than Eslint itself. 🤯", - "homepage": "https://github.com/adeira/universe/tree/master/src/eslint-runner", - "license": "MIT", - "private": false, - "version": "2.0.0", - "main": "index", - "sideEffects": false, - "dependencies": { - "@adeira/monorepo-utils": "^0.11.0", - "@babel/code-frame": "^7.12.11", - "@babel/register": "^7.13.14", - "@babel/runtime": "^7.13.10", - "chalk": "^4.1.0", - "create-jest-runner": "^0.7.0", - "is-ci": "^3.0.0", - "progress": "^2.0.3", - "strip-ansi": "^6.0.0", - "text-table": "^0.2.0" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } -} diff --git a/src/eslint-runner/reporter.js b/src/eslint-runner/reporter.js deleted file mode 100644 index 90e2341003..0000000000 --- a/src/eslint-runner/reporter.js +++ /dev/null @@ -1,94 +0,0 @@ -// @flow - -const ProgressBar = require('progress'); -const chalk = require('chalk'); - -/* eslint-disable no-console */ - -/*:: -type RunCompleteResults = {| - +numFailedTestSuites: number, - +numFailedTests: number, - +numPassedTestSuites: number, - +numPassedTests: number, - +numPendingTestSuites: number, - +numPendingTests: number, - +numRuntimeErrorTestSuites: number, - +numTodoTests: number, - +numTotalTestSuites: number, - +numTotalTests: number, - +openHandles: $ReadOnlyArray, // TODO - +snapshot: {| - +added: number, - +didUpdate: boolean, - +failure: boolean, - +filesAdded: number, - +filesRemoved: number, - +filesRemovedList: $ReadOnlyArray, - +filesUnmatched: number, - +filesUpdated: number, - +matched: number, - +total: number, - +unchecked: number, - +uncheckedKeysByFile: number, - +unmatched: number, - +updated: number, - |}, - +startTime: number, - +success: boolean, - +wasInterrupted: boolean, - +testResults: $ReadOnlyArray<{| - +numFailingTests: number, - +numPassingTests: number, - +numPendingTests: number, - +numTodoTests: number, - +failureMessage?: string, - |}>, -|}; -*/ - -class JestProgressBarReporter { - _numTotalTestSuites /*: number */ = 0; - _bar /*: typeof ProgressBar */; - - onRunStart(test /*: any */) /*: void */ { - const { numTotalTestSuites } = test; - this._numTotalTestSuites = numTotalTestSuites; - } - - onTestStart() /*: void */ { - if (this._bar == null) { - // Note that the space behind :total is necessary so that the cursor doesn't cover the last number of the total. - this._bar = new ProgressBar(':bar :current/:total ', { - complete: '█', - incomplete: '░', - total: this._numTotalTestSuites, - }); - } - } - - onTestResult() /*: void */ { - this._bar.tick(); - } - - onRunComplete(test /*: any */, results /*: RunCompleteResults */) /*: void */ { - // TODO: there might be an obsolete .snap file which causes Eslint Runner to fail (should be handle it?) - - results.testResults.forEach(({ failureMessage }) => { - if (failureMessage != null) { - console.log(failureMessage); - } - }); - - if (results.numFailedTests === 0) { - // Print basic stats when there are no failures: - console.warn( - 'Skipped files: %s (no changes)', - chalk.bold.yellow(String(results.numPendingTests)), - ); - console.warn('Checked files: %s', chalk.bold.green(String(results.numPassedTests))); - } - } -} - -module.exports = JestProgressBarReporter; diff --git a/src/eslint-runner/src/.eslintrc.js b/src/eslint-runner/src/.eslintrc.js deleted file mode 100644 index 5a98a18253..0000000000 --- a/src/eslint-runner/src/.eslintrc.js +++ /dev/null @@ -1,13 +0,0 @@ -// @flow strict - -/* eslint-disable no-unused-vars */ -const OFF = 0; -const WARN = 1; -const ERROR = 2; -/* eslint-enable no-unused-vars */ - -module.exports = { - rules: { - 'no-console': OFF, - }, -}; diff --git a/src/eslint-runner/src/__tests__/__snapshots__/codeframe.test.js.snap b/src/eslint-runner/src/__tests__/__snapshots__/codeframe.test.js.snap deleted file mode 100644 index 96b941dc7d..0000000000 --- a/src/eslint-runner/src/__tests__/__snapshots__/codeframe.test.js.snap +++ /dev/null @@ -1,110 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`prints the error as expected 1`] = ` -"TODO (rule-id-111) at src/sleepSort.js:4:0 - 2 | - 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -> 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ too ridiculous - 5 | setTimeout(() => console.log(num), num); - 6 | }); - 7 | - - -ERROR (rule-id-111) at src/sleepSort.js:4:0 - 2 | - 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -> 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ too ridiculous - 5 | setTimeout(() => console.log(num), num); - 6 | }); - 7 | - -" -`; - -exports[`prints the warnings first 1`] = ` -"TODO (rule-id-111) at src/sleepSort.js:4:0 - 2 | - 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -> 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ too ridiculous - 5 | setTimeout(() => console.log(num), num); - 6 | }); - 7 | - - -TODO (rule-id-111) at src/sleepSort.js:4:0 - 2 | - 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -> 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ too ridiculous - 5 | setTimeout(() => console.log(num), num); - 6 | }); - 7 | - - -TODO (rule-id-111) at src/sleepSort.js:4:0 - 2 | - 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -> 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ too ridiculous - 5 | setTimeout(() => console.log(num), num); - 6 | }); - 7 | - - -TODO (rule-id-111) at src/sleepSort.js:4:0 - 2 | - 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -> 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ too ridiculous - 5 | setTimeout(() => console.log(num), num); - 6 | }); - 7 | - - -ERROR at src/sleepSort.js:3:1 - 1 | // @flow strict - 2 | -> 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 - | ^ Unused eslint-disable directive (MOCK) - 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - 5 | setTimeout(() => console.log(num), num); - 6 | }); - - -ERROR (rule-id-111) at src/sleepSort.js:4:0 - 2 | - 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -> 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ too ridiculous - 5 | setTimeout(() => console.log(num), num); - 6 | }); - 7 | - - -ERROR (rule-id-111) at src/sleepSort.js:4:0 - 2 | - 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -> 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ too ridiculous - 5 | setTimeout(() => console.log(num), num); - 6 | }); - 7 | - -" -`; - -exports[`prints unused eslint-disable directive correctly 1`] = ` -"ERROR at src/sleepSort.js:3:1 - 1 | // @flow strict - 2 | -> 3 | // https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 - | ^ Unused eslint-disable directive (MOCK) - 4 | [3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - 5 | setTimeout(() => console.log(num), num); - 6 | }); - -" -`; diff --git a/src/eslint-runner/src/__tests__/codeframe.test.js b/src/eslint-runner/src/__tests__/codeframe.test.js deleted file mode 100644 index 78f61291bd..0000000000 --- a/src/eslint-runner/src/__tests__/codeframe.test.js +++ /dev/null @@ -1,70 +0,0 @@ -// @flow - -import fs from 'fs'; -import path from 'path'; -import stripAnsi from 'strip-ansi'; - -import codeframe, { type Results } from '../codeframe'; - -function getMockMessage(severity: 'warning' | 'error') { - return { - ruleId: 'rule-id-111', - severity: severity === 'warning' ? 1 : 2, - message: 'too ridiculous', - line: 4, - column: 0, - nodeType: 'mock', - messageId: 'mock', - endLine: 4, - endColumn: 27, - }; -} - -function getMockUnusedDirectiveMessage() { - return { - ruleId: null, - message: 'Unused eslint-disable directive (MOCK).', - line: 3, - column: 1, - severity: 2, - nodeType: null, - }; -} - -function getMockResults(messages): Results { - return [ - { - filePath: 'src/sleepSort.js', - messages, - errorCount: 1, - warningCount: 1, - fixableErrorCount: 0, - fixableWarningCount: 0, - source: fs.readFileSync(path.join(__dirname, 'sleepSort.js'), 'utf8'), - }, - ]; -} - -it('prints the error as expected', () => { - const results = getMockResults([getMockMessage('warning'), getMockMessage('error')]); - expect(stripAnsi(codeframe(results, { highlightCode: false }))).toMatchSnapshot(); -}); - -it('prints the warnings first', () => { - const results = getMockResults([ - getMockUnusedDirectiveMessage(), - getMockMessage('error'), - getMockMessage('warning'), - getMockMessage('error'), - getMockMessage('warning'), - getMockMessage('warning'), - getMockMessage('warning'), - ]); - - expect(stripAnsi(codeframe(results, { highlightCode: false }))).toMatchSnapshot(); -}); - -it('prints unused eslint-disable directive correctly', () => { - const results = getMockResults([getMockUnusedDirectiveMessage()]); - expect(stripAnsi(codeframe(results, { highlightCode: false }))).toMatchSnapshot(); -}); diff --git a/src/eslint-runner/src/__tests__/shouldLintAll.test.js b/src/eslint-runner/src/__tests__/shouldLintAll.test.js deleted file mode 100644 index f8341efb6c..0000000000 --- a/src/eslint-runner/src/__tests__/shouldLintAll.test.js +++ /dev/null @@ -1,30 +0,0 @@ -// @flow strict - -import shouldLintAll from '../shouldLintAll'; - -test.each([ - '.eslintrc', - '.eslintrc.js', - '.eslintrc.yml', - '.eslintrc.yaml', - '.eslintrc.json', - 'src/packages/relay/.eslintrc.js', - '/Users/TEST/universe/src/packages/relay/.eslintrc.js', - 'package.json', - 'src/packages/relay/package.json', - '/Users/code/universe/src/packages/relay/package.json', - '.eslintignore', -])('filename "%s" IS eslint config file', (filename) => { - expect(shouldLintAll(filename)).toBe(true); -}); - -test.each([ - 'eslintrc.yaml', - '.eslintrc.ts', - '.eslintrc.jsonp', - '.eslintrc/xyz', - 'src/.eslintrc/test', - 'src/test/.eslintignore', -])('filename "%s" IS NOT eslint config file', (filename) => { - expect(shouldLintAll(filename)).toBe(false); -}); diff --git a/src/eslint-runner/src/__tests__/sleepSort.js b/src/eslint-runner/src/__tests__/sleepSort.js deleted file mode 100644 index 7188dcc16e..0000000000 --- a/src/eslint-runner/src/__tests__/sleepSort.js +++ /dev/null @@ -1,6 +0,0 @@ -// @flow strict - -// https://twitter.com/JavaScriptDaily/status/856267407106682880 😇 -[3, 5, 1, 8, 2, 4, 9, 6, 7].forEach((num) => { - setTimeout(() => console.log(num), num); -}); diff --git a/src/eslint-runner/src/codeframe.js b/src/eslint-runner/src/codeframe.js deleted file mode 100644 index 98c7a083a3..0000000000 --- a/src/eslint-runner/src/codeframe.js +++ /dev/null @@ -1,109 +0,0 @@ -// @flow - -const path = require('path'); -const chalk = require('chalk'); -const { codeFrameColumns } = require('@babel/code-frame'); - -/*:: - -// https://eslint.org/docs/developer-guide/nodejs-api#-lintresult-type -export type Results = $ReadOnlyArray<{ - +filePath: string, - +messages: $ReadOnlyArray<{ - +ruleId: string | null, - +severity: 1 | 2, - +message: string, - +line?: number, - +column?: number, - +endLine?: number, - +endColumn?: number, - +fatal?: boolean, - ... - }>, - +fixableErrorCount: number, - +fixableWarningCount: number, - +errorCount: number, - +warningCount: number, - +output?: string, - +source: string, - ... -}> - -type Options = {| - +highlightCode: boolean, -|} - -*/ - -function formatFilePath(filePath, line, column) { - let relPath = path.relative(process.cwd(), filePath); - - if (line != null && column != null) { - relPath += `:${line}:${column}`; - } - - return chalk.green(relPath); -} - -function formatMessage(message, parentResult, options) { - const type = - message.fatal || message.severity === 2 ? chalk.red.bold('ERROR') : chalk.magenta.bold('TODO'); - const msg = `${chalk.bold(message.message.replace(/(?[^ ])\.$/u, '$1'))}`; - const ruleId = - message.fatal === true || message.ruleId == null ? '' : chalk.dim(`(${message.ruleId})`); - const filePath = formatFilePath(parentResult.filePath, message.line, message.column); - const sourceCode = parentResult.output != null ? parentResult.output : parentResult.source; - - const firstLine = [`${type}`, ruleId ? `${ruleId}` : '', `at ${filePath}`] - .filter(String) - .join(' '); - - const result = [firstLine]; - - if (sourceCode) { - const location = { - start: { line: message.line, column: message.column }, - end: undefined, - }; - if (message.endLine != null && message.endColumn != null) { - location.end = { line: message.endLine, column: message.endColumn }; - } - result.push( - codeFrameColumns(sourceCode, location, { - highlightCode: true, - ...options, - message: msg, - }), - ); - } - - return result.join('\n'); -} - -module.exports = function (results /*: Results */, options /*: ?Options */) /*: string */ { - let errors = 0; - let warnings = 0; - - const resultsWithMessages = results.filter((result) => result.messages.length > 0); - - const outputWarnings = resultsWithMessages.reduce((resultsOutput, result) => { - const messages = result.messages - .filter((message) => message.severity === 1) // warnings - .map((message) => `${formatMessage(message, result, options)}\n\n`); - - warnings += result.warningCount; - return resultsOutput.concat(messages); - }, []); - - const outputErrors = resultsWithMessages.reduce((resultsOutput, result) => { - const messages = result.messages - .filter((message) => message.severity === 2) // errors - .map((message) => `${formatMessage(message, result, options)}\n\n`); - - errors += result.errorCount; - return resultsOutput.concat(messages); - }, []); - - const output = outputWarnings.concat(outputErrors).join('\n'); - return errors + warnings > 0 ? output : ''; -}; diff --git a/src/eslint-runner/src/run.js b/src/eslint-runner/src/run.js deleted file mode 100644 index 3593206f1e..0000000000 --- a/src/eslint-runner/src/run.js +++ /dev/null @@ -1,162 +0,0 @@ -// @flow - -require('@babel/register'); // to be able to use non-transpiled '@adeira/monorepo-utils' here - -const { pass, fail, skip } = require('create-jest-runner'); -const CLIEngine = require('eslint').CLIEngine; -const isCI = require('is-ci'); -const { Git } = require('@adeira/monorepo-utils'); - -const formatter = require('./codeframe'); -const shouldLintAll = require('./shouldLintAll').default; - -const PERFORM_FIXES = isCI === false; -const cliEngine = new CLIEngine({ - fix: PERFORM_FIXES, - reportUnusedDisableDirectives: true, -}); - -/*:: - -type Options = {| - +testPath: string, - +config: { [key: string]: any, ... }, - +globalConfig: { [key: string]: any, ... }, - +extraOptions: {| - +runAll: boolean, - +noWarnings: boolean, - |} -|} - -*/ - -// TODO: we should eventually get rid of 'create-jest-runner' dependency and use our own -// implementation with this built-in mechanism. This way we don't have to iterate all the files -// and skipping them. -const getChangedFiles = () => { - try { - // This fails if git is not initialised or if user has no remote origin - // Let's catch the error, and just lint all instead rather than crashing - return Git.getChangesToTest(); - } catch { - return null; - } -}; - -const changedFiles = getChangedFiles(); - -module.exports = ({ testPath, extraOptions } /*: Options */) /*: { +[string]: mixed, ... } */ => { - const start = Date.now(); - let runAll = extraOptions.runAll || changedFiles === null; - - if (changedFiles !== null) { - for (const changedFile of changedFiles) { - if (shouldLintAll(changedFile)) { - runAll = true; - break; - } - } - } - - if (cliEngine.isPathIgnored(testPath)) { - return skip({ - start, - end: start, - test: { - path: testPath, - }, - }); - } - - if (runAll === false && changedFiles !== null) { - const normalizedPath = testPath.replace(process.cwd(), '').replace(/^\//, ''); - if (changedFiles.includes(normalizedPath) === false) { - return skip({ - start, - end: start, - test: { - path: testPath, - }, - }); - } - } - - const report = cliEngine.executeOnFiles([testPath]); - const errorResults = extraOptions.noWarnings - ? CLIEngine.getErrorResults(report.results) - : report.results; - - if (PERFORM_FIXES) { - CLIEngine.outputFixes(report); - } - - const end = Date.now(); - const result = report.results[0]; - - if (result.errorCount === 0 && result.warningCount > 0 && extraOptions.noWarnings === false) { - // it has some warnings (we render them as TODOs) - return todoWithMessage({ - start, - end, - test: { - path: testPath, - errorMessage: formatter(errorResults), - }, - }); - } else if (result.errorCount > 0) { - return fail({ - start, - end, - test: { - path: testPath, - errorMessage: formatter(errorResults), - }, - }); - } - - return pass({ - start, - end, - test: { - path: testPath, - }, - }); -}; - -function todoWithMessage({ start, end, test }) { - return { - console: null, - failureMessage: test.errorMessage, - numFailingTests: 0, - numPassingTests: 0, - numPendingTests: 0, - numTodoTests: 1, - perfStats: { - end: new Date(start).getTime(), - start: new Date(end).getTime(), - }, - skipped: false, - snapshot: { - added: 0, - fileDeleted: false, - matched: 0, - unchecked: 0, - unmatched: 0, - updated: 0, - }, - sourceMaps: {}, - testExecError: null, - testFilePath: test.path, - testResults: [ - { - ancestorTitles: [], - duration: end - start, - failureMessages: [test.errorMessage], - fullName: test.path, - numPassingAsserts: 1, - status: 'passed', - title: '', - }, - ], - }; -} diff --git a/src/eslint-runner/src/shouldLintAll.js b/src/eslint-runner/src/shouldLintAll.js deleted file mode 100644 index d26c0e6e41..0000000000 --- a/src/eslint-runner/src/shouldLintAll.js +++ /dev/null @@ -1,7 +0,0 @@ -// @flow strict - -export default function shouldLintAll(filename: string): boolean { - // Eslint configs can be nested (not only the root path). - // See: https://eslint.org/docs/user-guide/configuring#configuration-file-formats - return /\.eslintrc(?:\.(?:js(?:on)?|ya?ml))?$|package\.json$|^\.eslintignore$/.test(filename); -} diff --git a/src/eslint-runner/src/verifyPackageTree.js b/src/eslint-runner/src/verifyPackageTree.js deleted file mode 100644 index 31ce555f7e..0000000000 --- a/src/eslint-runner/src/verifyPackageTree.js +++ /dev/null @@ -1,54 +0,0 @@ -// @flow - -const fs = require('fs'); -const path = require('path'); - -/** - * Inspiration: https://github.com/facebook/create-react-app/blob/3495286f8f3835d55cbdedbc881ae481eb0a3c65/packages/react-scripts/scripts/utils/verifyPackageTree.js - * MIT licenced. - */ -module.exports = function verifyPackageTree() { - const ownPackageJson = require('../package.json'); - const depsToCheck = Object.keys(ownPackageJson.dependencies).filter((dep) => - dep.startsWith('eslint-plugin'), - ); - - const expectedVersionsByDep = {}; - depsToCheck.forEach((dep) => { - expectedVersionsByDep[dep] = ownPackageJson.dependencies[dep].replace(/^[~^]/, ''); - }); - - // Verify we don't have other versions up the tree. - let currentDir = __dirname; - while (true) { - const previousDir = currentDir; - currentDir = path.resolve(currentDir, '..'); - if (currentDir === previousDir) { - break; // We've reached the root. - } - const maybeNodeModules = path.resolve(currentDir, 'node_modules'); - if (!fs.existsSync(maybeNodeModules)) { - continue; - } - depsToCheck.forEach((dep) => { - const maybeDep = path.resolve(maybeNodeModules, dep); - if (!fs.existsSync(maybeDep)) { - return; - } - const maybeDepPackageJson = path.resolve(maybeDep, 'package.json'); - if (!fs.existsSync(maybeDepPackageJson)) { - return; - } - const depPackageJson = JSON.parse(fs.readFileSync(maybeDepPackageJson, 'utf8')); - const expectedVersion = expectedVersionsByDep[dep]; - if (depPackageJson.version !== expectedVersion) { - console.warn( - 'There might be a problem with the following plugin: %s (used %s but expected %s)', - dep, - depPackageJson.version, - expectedVersion, - ); - } - }); - } -}; diff --git a/yarn.lock b/yarn.lock index c6c744b337..3421ff226f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6479,13 +6479,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -create-jest-runner@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/create-jest-runner/-/create-jest-runner-0.7.0.tgz#c5b438ab551fc727fda2db1828119a8b5c2408e2" - integrity sha512-lPG9GhfxrpcltKEls4/XsbkW6SEuzk9frCTC0SEA1ZVwk5XBYyxdmoqg/h7iKr9Nkq2uAg2Zcs+D4ZzUOuKabQ== +create-jest-runner@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/create-jest-runner/-/create-jest-runner-0.6.0.tgz#9ca6583d969acc15cdc21cd07d430945daf83de6" + integrity sha512-9ibH8XA4yOJwDLRlzIUv5Ceg2DZFrQFjEtRKplVP6scGKwoz28V27xPHTbXziq2LePAD/xXlJlywhUq1dtF+nw== dependencies: - chalk "^4.1.0" - jest-worker "^26.3.0" + chalk "^3.0.0" + jest-worker "^25.1.0" throat "^5.0.0" create-react-context@0.3.0: @@ -10891,6 +10891,15 @@ jest-resolve@^26.6.2: resolve "^1.18.1" slash "^3.0.0" +jest-runner-eslint@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/jest-runner-eslint/-/jest-runner-eslint-0.10.0.tgz#5d7197d1e982b2cceea9e65f078dc371cc4a9815" + integrity sha512-XXKz2hMLGvyH50i29UcNQDQY2Sj1hLuCn7H3otMdeOB2LOzdHXXif3RXX+8m/eAewflB5RqqqlF1K7FozYZKrg== + dependencies: + chalk "^3.0.0" + cosmiconfig "^6.0.0" + create-jest-runner "^0.6.0" + jest-runner@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" @@ -11077,7 +11086,15 @@ jest-worker@27.0.0-next.5: merge-stream "^2.0.0" supports-color "^8.0.0" -jest-worker@^26.2.1, jest-worker@^26.3.0, jest-worker@^26.5.0, jest-worker@^26.6.1, jest-worker@^26.6.2: +jest-worker@^25.1.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1" + integrity sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw== + dependencies: + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest-worker@^26.2.1, jest-worker@^26.5.0, jest-worker@^26.6.1, jest-worker@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== @@ -14155,7 +14172,7 @@ process@0.11.10, process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -progress@^2.0.0, progress@^2.0.3: +progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==