Skip to content

Commit

Permalink
Migrate to core_d v5 and implement common package manager file checks
Browse files Browse the repository at this point in the history
  • Loading branch information
mantoni committed May 26, 2022
1 parent a2331e3 commit 96e34ef
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 116 deletions.
62 changes: 62 additions & 0 deletions lib/caches.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use strict';

const path = require('path');
const LRU = require('nanolru');
const resolver = require('./resolver');
const eslint_path = require('./eslint-path');
const files_hash = require('./files-hash');

const lru_cache = new LRU(10);
const check_files = [
'package.json',
'package-lock.json',
'npm-shrinkwrap.json',
'yarn.lock',
'pnpm-lock.yaml'
];

exports.lru_cache = lru_cache;

exports.getCache = getCache;

async function getCache(cwd, eslint_path_arg) {
let cache = lru_cache.get(cwd);
if (!cache) {
cache = createCache(cwd, eslint_path_arg);
if (cache) {
cache.filesChanged = await files_hash.filesHash(cwd, check_files);
}
return cache;
}
const { filesChanged } = cache;
if (filesChanged && await filesChanged()) {
clearRequireCache(cwd);
cache = createCache(cwd, eslint_path_arg);
cache.filesChanged = filesChanged;
}
return cache;
}

function createCache(cwd, eslint_path_arg) {
const absolute_eslint_path = eslint_path.resolve(cwd, eslint_path_arg);

if (!absolute_eslint_path) {
return null;
}

return lru_cache.set(cwd, {
eslint: require(absolute_eslint_path),
// use chalk from eslint
chalk: require(resolver.resolve('chalk', {
paths: [path.dirname(absolute_eslint_path)]
}))
});
}

function clearRequireCache(cwd) {
Object.keys(require.cache)
.filter(key => key.startsWith(cwd))
.forEach((key) => {
delete require.cache[key];
});
}
45 changes: 4 additions & 41 deletions lib/linter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@

const fs = require('fs');
const path = require('path');
const LRU = require('nanolru');
const resolver = require('./resolver');
const eslint_path = require('./eslint-path');
const options_cliengine = require('./options-cliengine');
const options_eslint = require('./options-eslint');
const caches = require('./caches');

function translateOptionsCLIEngine(cliOptions, cwd) {
return {
Expand Down Expand Up @@ -82,32 +80,6 @@ function translateOptionsESLint(cliOptions, cwd) {
};
}

const eslintCache = new LRU(10);

function createCache(cwd, eslint_path_arg) {
const absolute_eslint_path = eslint_path.resolve(cwd, eslint_path_arg);

if (!absolute_eslint_path) {
return false;
}

return eslintCache.set(cwd, {
eslint: require(absolute_eslint_path),
// use chalk from eslint
chalk: require(resolver.resolve('chalk', {
paths: [path.dirname(absolute_eslint_path)]
}))
});
}

function clearRequireCache(cwd) {
Object.keys(require.cache)
.filter(key => key.startsWith(cwd))
.forEach((key) => {
delete require.cache[key];
});
}

function countErrors(results) {
let errorCount = 0;
let warningCount = 0;
Expand Down Expand Up @@ -280,7 +252,7 @@ function executeWithCLIEngine(CLIEngine, cwd, opts, text, callback) {
/*
* The core_d service entry point.
*/
exports.invoke = async function (cwd, args, text, hash, callback) {
exports.invoke = async function (cwd, args, text, callback) {
process.chdir(cwd);

let eslint_path_arg;
Expand All @@ -297,18 +269,11 @@ exports.invoke = async function (cwd, args, text, hash, callback) {
}
}

let cache = eslintCache.get(cwd);
if (!cache) {
cache = createCache(cwd, eslint_path_arg);
} else if (hash !== cache.hash) {
clearRequireCache(cwd);
cache = createCache(cwd, eslint_path_arg);
}
const cache = await caches.getCache(cwd, eslint_path_arg);
if (!cache) {
callback(null);
return;
}
cache.hash = hash;

const options = cache.eslint.ESLint
? options_eslint
Expand Down Expand Up @@ -351,13 +316,11 @@ exports.invoke = async function (cwd, args, text, hash, callback) {
}
};

exports.cache = eslintCache;

/*
* The core_d status hook.
*/
exports.getStatus = function () {
const { keys } = eslintCache;
const { keys } = caches.lru_cache;
if (keys.length === 0) {
return 'No instances cached.';
}
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"url": "https://github.com/mantoni/eslint_d.js.git"
},
"dependencies": {
"core_d": "^4.0.0",
"core_d": "^5.0.1",
"eslint": "^8.12.0",
"nanolru": "^1.0.0",
"optionator": "^0.9.1"
Expand Down
110 changes: 110 additions & 0 deletions test/caches-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*eslint-env mocha*/
'use strict';

const { assert, refute, sinon } = require('@sinonjs/referee-sinon');
const eslint_path = require('../lib/eslint-path');
const files_hash = require('../lib/files-hash');
const { getCache, lru_cache } = require('../lib/caches');

describe('test/caches', () => {
const cwd = process.cwd();

afterEach(() => {
lru_cache.clear();
sinon.restore();
});

it('calls eslint_path.resolve with cwd and eslint_path_arg', async () => {
sinon.replace(eslint_path, 'resolve', sinon.fake.returns(null));

await getCache(cwd, 'something');

assert.calledOnceWith(eslint_path.resolve, cwd, 'something');
});

it('calls filesHash with cwd and common package manager files', async () => {
sinon.replace(files_hash, 'filesHash', sinon.fake.resolves(() => {}));

await getCache(cwd);

assert.calledOnceWith(files_hash.filesHash, cwd, [
'package.json',
'package-lock.json',
'npm-shrinkwrap.json',
'yarn.lock',
'pnpm-lock.yaml'
]);
});

it('creates a new cache with filesChanged', async () => {
const filesChanged = sinon.fake();
sinon.replace(files_hash, 'filesHash', sinon.fake.resolves(filesChanged));

const cache = await getCache(cwd);

refute.isNull(cache);
assert.same(lru_cache.get(cwd), cache);
assert.same(cache.filesChanged, filesChanged);
});

it('returns null if absolute eslint path cannot be resolved', async () => {
sinon.replace(files_hash, 'filesHash', sinon.fake());
sinon.replace(eslint_path, 'resolve', sinon.fake.returns(null));

const cache = await getCache('./some/path');

assert.isNull(cache);
refute.called(files_hash.filesHash);
});

it('returns same cache on second call if filesChanged is null', async () => {
sinon.replace(files_hash, 'filesHash', sinon.fake.resolves(null));

const cache_1 = await getCache(cwd);
const cache_2 = await getCache(cwd);

assert.same(cache_1, cache_2);
});

it('returns same cache on second call if filesChanged returns false',
async () => {
const filesChanged = sinon.fake.resolves(false);
sinon.replace(files_hash, 'filesHash', sinon.fake.resolves(filesChanged));

const cache_1 = await getCache(cwd);
const cache_2 = await getCache(cwd);

assert.calledOnce(filesChanged);
assert.same(cache_1, cache_2);
});

it('returns new cache on second call if filesChanged returns true',
async () => {
const filesChanged = sinon.fake.resolves(true);
sinon.replace(files_hash, 'filesHash', sinon.fake.resolves(filesChanged));

const cache_1 = await getCache(cwd);
const cache_2 = await getCache(cwd);

assert.calledOnce(filesChanged);
refute.same(cache_1, cache_2);
assert.same(cache_1.filesChanged, cache_2.filesChanged);
});

it('returns new cache on second call if cwd is different',
async () => {
sinon.replace(files_hash, 'filesHash',
sinon.fake(() => Promise.resolve(sinon.fake())));

const cache_1 = await getCache(cwd);
const cache_2 = await getCache('./other/path');

refute.same(cache_1, cache_2);
assert.calledTwice(files_hash.filesHash);
assert.calledWith(files_hash.filesHash, cwd);
assert.calledWith(files_hash.filesHash, './other/path');
refute.same(cache_1.filesChanged, cache_2.filesChanged);
refute.called(cache_1.filesChanged);
refute.called(cache_2.filesChanged);
});
});
Loading

0 comments on commit 96e34ef

Please sign in to comment.