Skip to content

Commit

Permalink
feat: target ESLint v9
Browse files Browse the repository at this point in the history
  • Loading branch information
Marsup committed Aug 14, 2024
1 parent 945503a commit 4c6c434
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 77 deletions.
9 changes: 0 additions & 9 deletions .eslintignore

This file was deleted.

20 changes: 20 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

const HapiPlugin = require('@hapi/eslint-plugin');

module.exports = [
{
ignores: [
'node_modules/',
'test_runner/',
'test/coverage/',
'test/cli/',
'test/cli_*/',
'test/lint/',
'test/override/',
'test/plan/',
'test/transform/'
]
},
...HapiPlugin.configs.module
];
6 changes: 3 additions & 3 deletions lib/linter/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';

module.exports = {
extends: 'plugin:@hapi/module'
};
const HapiPlugin = require('@hapi/eslint-plugin');

module.exports = [...HapiPlugin.configs.module];
52 changes: 37 additions & 15 deletions lib/linter/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

const Fs = require('fs');
const Path = require('path');

const Eslint = require('eslint');
const Hoek = require('@hapi/hoek');
Expand All @@ -18,31 +17,47 @@ exports.lint = async function () {

const options = process.argv[2] ? JSON.parse(process.argv[2]) : undefined;

if (!Fs.existsSync('.eslintrc.js') &&
!Fs.existsSync('.eslintrc.cjs') && // Needed for projects with "type": "module"
!Fs.existsSync('.eslintrc.yaml') &&
!Fs.existsSync('.eslintrc.yml') &&
!Fs.existsSync('.eslintrc.json') &&
!Fs.existsSync('.eslintrc')) {
configuration.overrideConfigFile = Path.join(__dirname, '.eslintrc.js');
let usingDefault = false;

if (!Fs.existsSync('eslint.config.js') &&
!Fs.existsSync('eslint.config.cjs') &&
!Fs.existsSync('eslint.config.mjs')) {
// No configuration file found, using the default one
usingDefault = true;
configuration.baseConfig = require('./.eslintrc.js');
configuration.overrideConfigFile = true;
}

if (options) {
Hoek.merge(configuration, options, true, false);
}

if (!configuration.extensions) {
configuration.extensions = ['.js', '.cjs', '.mjs'];
// Only the default configuration should be altered, otherwise the user's configuration should be used as is
if (usingDefault) {
if (!configuration.extensions) {
const extensions = ['js', 'cjs', 'mjs'];

if (configuration.typescript) {
extensions.push('ts');
}

if (configuration.typescript) {
configuration.extensions.push('.ts');
configuration.baseConfig.unshift({
files: extensions.map((ext) => `**/*.${ext}`)
});
}
}

if (configuration.typescript) {
delete configuration.typescript;
if (configuration.ignores) {
configuration.baseConfig.unshift({
ignores: configuration.ignores
});
}
}

delete configuration.extensions;
delete configuration.typescript;
delete configuration.ignores;


let results;
try {
const eslint = new Eslint.ESLint(configuration);
Expand All @@ -66,6 +81,13 @@ exports.lint = async function () {

transformed.errors = result.messages.map((err) => {

if (err.messageTemplate === 'all-matched-files-ignored') {
return {
severity: 'ERROR',
message: err.message
};
}

return {
line: err.line,
severity: err.severity === 1 ? 'WARNING' : 'ERROR',
Expand Down
14 changes: 11 additions & 3 deletions lib/modules/coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ const Transform = require('./transform');

const internals = {
_state: Symbol.for('@hapi/lab/coverage/_state'),
eslint: new ESLint.ESLint({ baseConfig: Eslintrc })
eslint: new ESLint.ESLint({
baseConfig: Eslintrc,
overrideConfigFile: true,
ignore: false
})
};


Expand Down Expand Up @@ -111,7 +115,7 @@ internals.prime = function (extension, ctx) {
require.extensions[extension] = function (localModule, filename) {

// We never want to instrument eslint configs in order to avoid infinite recursion
if (Path.basename(filename, extension) !== '.eslintrc') {
if (!['.eslintrc', 'eslint.config'].includes(Path.basename(filename, extension))) {
for (let i = 0; i < internals.state.patterns.length; ++i) {
if (internals.state.patterns[i].test(filename.replace(/\\/g, '/'))) {
return localModule._compile(internals.instrument(filename, ctx), filename);
Expand Down Expand Up @@ -763,9 +767,13 @@ internals.context = async (options) => {

// The parserOptions are shared by all files for coverage purposes, based on
// the effective eslint config for a hypothetical file {coveragePath}/x.js
const { parserOptions } = await internals.eslint.calculateConfigForFile(
const calculated = await internals.eslint.calculateConfigForFile(
Path.join(options.coveragePath || '', 'x.js')
);
const parserOptions = {
...calculated.languageOptions,
...calculated.languageOptions?.parserOptions
};

return { parserOptions };
};
14 changes: 5 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,14 @@
"bin/lab",
"lib"
],
"eslintConfig": {
"extends": [
"plugin:@hapi/module"
]
},
"dependencies": {
"@babel/core": "^7.16.0",
"@babel/eslint-parser": "^7.16.0",
"@babel/eslint-parser": "^7.25.1",
"@hapi/bossy": "^6.0.0",
"@hapi/eslint-plugin": "^6.0.0",
"@hapi/hoek": "^11.0.2",
"diff": "^5.0.0",
"eslint": "8.x.x",
"eslint": "9.x.x",
"find-rc": "4.x.x",
"globby": "^11.1.0",
"handlebars": "4.x.x",
Expand All @@ -48,13 +43,14 @@
"devDependencies": {
"@hapi/code": "^9.0.0",
"@hapi/somever": "^4.0.0",
"@types/eslint": "^9.6.0",
"@types/node": "^18.11.17",
"@typescript-eslint/parser": "^5.62.0",
"cpr": "3.x.x",
"lab-event-reporter": "1.x.x",
"semver": "7.x.x",
"tsconfig-paths": "^4.0.0",
"typescript": "^4.5.4"
"typescript": "^4.5.4",
"typescript-eslint": "^8.1.0"
},
"bin": {
"lab": "./bin/lab"
Expand Down
6 changes: 3 additions & 3 deletions test/coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -566,19 +566,19 @@ describe('Coverage', () => {
it('sorts file paths in report', async () => {

const files = global.__$$labCov.files;
const paths = ['/a/b', '/a/b/c', '/a/c/b', '/a/c', '/a/b/c', '/a/b/a'];
const paths = ['./a/b', './a/b/c', './a/c/b', './a/c', './a/b/c', './a/b/a'];
paths.forEach((path) => {

files[path] = { source: [] };
});

const cov = await Lab.coverage.analyze({ coveragePath: '/a' });
const cov = await Lab.coverage.analyze({ coveragePath: './a' });
const sorted = cov.files.map((file) => {

return file.filename;
});

expect(sorted).to.equal(['/a/b', '/a/c', '/a/b/a', '/a/b/c', '/a/c/b']);
expect(sorted).to.equal(['./a/b', './a/c', './a/b/a', './a/b/c', './a/c/b']);
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use strict';

const HapiPlugin = require('@hapi/eslint-plugin');

// this is a deliberately unused function that will reduce coverage percentage
// if it ends up getting instrumented, giving us something to assert against
const unusedMethod = () => {
console.log('hello world')
}

module.exports = {
extends: 'plugin:@hapi/module'
}
module.exports = [...HapiPlugin.configs.module]
13 changes: 0 additions & 13 deletions test/lint/eslint/esm/.eslintrc.cjs

This file was deleted.

22 changes: 22 additions & 0 deletions test/lint/eslint/esm/eslint.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict';

const HapiPlugin = require('@hapi/eslint-plugin');

module.exports = [
...HapiPlugin.configs.module,
{
languageOptions: {
parserOptions: {
sourceType: 'module'
}
}
},
{
files: ['*.cjs'],
languageOptions: {
parserOptions: {
sourceType: 'script'
}
}
}
];
5 changes: 0 additions & 5 deletions test/lint/eslint/typescript/.eslintrc.cjs

This file was deleted.

12 changes: 12 additions & 0 deletions test/lint/eslint/typescript/eslint.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

const HapiPlugin = require('@hapi/eslint-plugin');
const TsESLint = require('typescript-eslint');

module.exports = TsESLint.config(
{
files: ['**/*.ts']
},
...HapiPlugin.configs.module,
TsESLint.configs.base
);
1 change: 0 additions & 1 deletion test/lint/eslint/with_config/.eslintignore

This file was deleted.

9 changes: 0 additions & 9 deletions test/lint/eslint/with_config/.eslintrc.js

This file was deleted.

15 changes: 15 additions & 0 deletions test/lint/eslint/with_config/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

module.exports = [
{
ignores: ['*.ignore.*']
},
{
'rules': {
'eol-last': 2,
'no-unused-vars': 0,
'no-undef': 0
}
}
];

7 changes: 3 additions & 4 deletions test/linters.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ describe('Linters - eslint', () => {
{ line: 12, severity: 'WARNING', message: 'eol-last - Newline required at end of file but not found.' }
]);

const checkedCjsFile = eslintResults.find(({ filename }) => filename === Path.join(path, '.eslintrc.cjs'));
const checkedCjsFile = eslintResults.find(({ filename }) => filename === Path.join(path, 'eslint.config.cjs'));
expect(checkedCjsFile.errors).to.be.empty();
});

Expand Down Expand Up @@ -131,7 +131,6 @@ describe('Linters - eslint', () => {
const checkedFile = eslintResults.find(({ filename }) => filename.endsWith('.ts'));
expect(checkedFile).to.include({ filename: Path.join(path, 'fail.ts') });
expect(checkedFile.errors).to.include([
{ line: 1, severity: 'ERROR', message: `strict - Use the global form of 'use strict'.` },
{ line: 6, severity: 'ERROR', message: 'indent - Expected indentation of 4 spaces but found 1 tab.' },
{ line: 6, severity: 'ERROR', message: 'semi - Missing semicolon.' }
]);
Expand Down Expand Up @@ -195,15 +194,15 @@ describe('Linters - eslint', () => {

it('should pass options and not find any files', async () => {

const lintOptions = JSON.stringify({ extensions: ['.jsx'] });
const lintOptions = JSON.stringify({ extensions: ['.jsx'], ignores: ['**/*.js'] });
const path = Path.join(__dirname, 'lint', 'eslint', 'basic');
const result = await Linters.lint({ lintingPath: path, linter: 'eslint', 'lint-options': lintOptions });

expect(result).to.include('lint');

const eslintResults = result.lint;
expect(eslintResults).to.have.length(1);
expect(eslintResults[0].errors[0].message).to.contain('No files');
expect(eslintResults[0].errors[0].message).to.contain('All files matched by \'.\' are ignored.');
});

it('should fix lint rules when --lint-fix used', async (flags) => {
Expand Down

0 comments on commit 4c6c434

Please sign in to comment.