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 Oct 22, 2024
1 parent c10b2ae commit 27c5518
Show file tree
Hide file tree
Showing 24 changed files with 173 additions and 88 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
40 changes: 34 additions & 6 deletions lib/modules/coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ const SourceMap = require('../source-map');
const Transform = require('./transform');

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


Expand Down Expand Up @@ -111,7 +110,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 @@ -761,11 +760,40 @@ internals.file = async function (filename, data, options) {

internals.context = async (options) => {

const filePath = Path.join(options.coveragePath || '', 'x.js');
let calculated;

// 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(
Path.join(options.coveragePath || '', 'x.js')
);
try {
// Let's try first with eslint's native configuration detection
const eslint = new ESLint.ESLint({
ignore: false
});

calculated = await eslint.calculateConfigForFile(filePath);
}
catch (err) {
/* $lab:coverage:off$ */
if (err.messageTemplate !== 'config-file-missing') {
throw err;
}

// If the eslint config file is missing, we'll use the one provided by lab
const eslint = new ESLint.ESLint({
overrideConfig: Eslintrc,
overrideConfigFile: true,
ignore: false
});

calculated = await eslint.calculateConfigForFile(filePath);
/* $lab:coverage:on$ */
}

const parserOptions = {
...calculated.languageOptions,
...calculated.languageOptions?.parserOptions
};

return { parserOptions };
};
2 changes: 1 addition & 1 deletion lib/modules/lint.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ exports.lint = function (settings) {
try {
linterOptions = JSON.parse(settings['lint-options'] || '{}');
}
catch (err) {
catch {
return reject(new Error('lint-options could not be parsed'));
}

Expand Down
2 changes: 1 addition & 1 deletion lib/modules/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ exports.retrieveFile = function (path) {
try {
contents = Fs.readFileSync(path, 'utf8');
}
catch (e) {
catch {
contents = null;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/modules/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internals.transform = function (content, fileName) {
try {
var { config, error } = Typescript.readConfigFile(configFile, Typescript.sys.readFile);
}
catch (err) {
catch {
throw new Error(`Cannot find a tsconfig file for ${fileName}`);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ const internals = {};

// Prevent libraries like Sinon from clobbering global time functions

/* eslint-disable no-redeclare */
const Date = global.Date;
const setTimeout = global.setTimeout;
const clearTimeout = global.clearTimeout;
const setImmediate = global.setImmediate;
/* eslint-enable no-redeclare */


Error.stackTraceLimit = Infinity; // Set Error stack size
Expand Down
18 changes: 7 additions & 11 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/eslint-plugin": "^7.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 @@ -37,7 +32,7 @@
"will-call": "1.x.x"
},
"peerDependencies": {
"@hapi/eslint-plugin": "^6.0.0",
"@hapi/eslint-plugin": "^7.0.0",
"typescript": ">=3.6.5"
},
"peerDependenciesMeta": {
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
3 changes: 2 additions & 1 deletion test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Load modules

const ChildProcess = require('child_process');
// eslint-disable-next-line no-redeclare
const Crypto = require('crypto');
const Fs = require('fs');
const Http = require('http');
Expand Down Expand Up @@ -702,7 +703,7 @@ describe('CLI', () => {
try {
await unlink(outputPath);
}
catch (err) {
catch {

// Error is ok here
}
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]
4 changes: 2 additions & 2 deletions test/coverage/test-folder/test-name.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

// Load modules

const EslintConfig = require('./eslint.config');

// Declare internals

Expand All @@ -10,5 +10,5 @@ const internals = {};

exports.method = function () {

return;
return EslintConfig;
};
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.

Loading

0 comments on commit 27c5518

Please sign in to comment.