Skip to content

Commit

Permalink
feat: resolve rules exported by plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
philippfromme committed Mar 29, 2023
1 parent 4e403f0 commit c19c638
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 59 deletions.
41 changes: 28 additions & 13 deletions lib/resolver/node-resolver.js
Expand Up @@ -26,15 +26,30 @@ NodeResolver.prototype.resolveRule = function(pkg, ruleName) {

pkg = this.normalizePkg(pkg);

// (1) try resolving rule via $PKG.rules[$NAME]
try {
const instance = this.require(pkg);

const rules = instance.rules || {};

if (ruleName in rules) {
return rules[ruleName];
}
} catch (err) {

/* ignore */
}

// (2) try resolving rule via $PKG/rules/$NAME
try {
if (pkg === 'bpmnlint') {
return this.requireLocal(`../../rules/${ruleName}`);
} else {
return this.require(`${pkg}/rules/${ruleName}`);
}
} catch (err) {
throw new Error('Cannot resolve rule <' + ruleName + '> from <' + originalPkg + '>');
}
} catch (err) { /* ignore */ }

throw new Error('Cannot resolve rule <' + ruleName + '> from <' + originalPkg + '>');
};

NodeResolver.prototype.resolveConfig = function(pkg, configName) {
Expand All @@ -43,16 +58,7 @@ NodeResolver.prototype.resolveConfig = function(pkg, configName) {

pkg = this.normalizePkg(pkg);

// resolve config via $PKG/config/$NAME
try {
if (pkg === 'bpmnlint') {
return this.requireLocal(`../../config/${configName}`);
} else {
return this.require(`${pkg}/config/${configName}`);
}
} catch (err) { /* ignore */ }

// resolve config via $PKG.configs[$NAME]
// (1) try resolving config via $PKG.configs[$NAME]
try {
const instance = this.require(pkg);

Expand All @@ -66,6 +72,15 @@ NodeResolver.prototype.resolveConfig = function(pkg, configName) {
/* ignore */
}

// (2) try resolving config via $PKG/config/$NAME
try {
if (pkg === 'bpmnlint') {
return this.requireLocal(`../../config/${configName}`);
} else {
return this.require(`${pkg}/config/${configName}`);
}
} catch (err) { /* ignore */ }

throw new Error(
'Cannot resolve config <' + configName + '> from <' + originalPkg + '>'
);
Expand Down
37 changes: 32 additions & 5 deletions lib/support/compile-config.js
Expand Up @@ -93,12 +93,39 @@ export default bundle;
pkg, ruleName
} = linter.parseRuleName(key);

return `
import rule_${idx} from '${resolver.normalizePkg(pkg)}/rules/${ruleName}';
cache['${pkg}/${ruleName}'] = rule_${idx};`;
return createImportStatement(pkg, ruleName, idx, resolver);
}).filter(e => e).join('\n');

return `${preambleCode}\n\n${importCode}`;
return `${preambleCode}${importCode}`;
}

module.exports = compileConfig;
module.exports = compileConfig;

function createImportStatement(pkg, ruleName, idx, resolver) {
const originalPkg = pkg;

pkg = resolver.normalizePkg(pkg);

// (1) try resolving rule via $PKG.rules[$NAME]
try {
const instance = resolver.require(pkg);

const rules = instance.rules || {};

if (ruleName in rules) {
return `
import exports_${ idx } from '${ pkg }';
cache['${ originalPkg }/${ ruleName }'] = exports_${ idx }.rules['${ ruleName }'];`;
}
} catch (err) {

/* ignore */
}

// (2) resolve rule via $PKG/rules/$NAME
return `
import rule_${ idx } from '${ pkg }/rules/${ ruleName }';
cache['${ originalPkg }/${ ruleName }'] = rule_${ idx };`;
}
87 changes: 71 additions & 16 deletions test/spec/resolver/node-resolver-spec.js
Expand Up @@ -22,8 +22,19 @@ describe('resolver/node-resolver', function() {
* Resolve local plugin rules.
*/

// mock resolving of rules ($PKG/rules/$NAME)
if (path === './rules/rule') {
// mock resolving of exported rules ($PKG.rules[$NAME])
if (path === '.') {
return {
rules: {
exported: {
path: './lib/rules/exported'
}
}
};
}

// mock resolving of non-exported rules ($PKG/rules/$NAME)
if (path === './rules/non-exported') {
return {
path
};
Expand All @@ -33,8 +44,19 @@ describe('resolver/node-resolver', function() {
* Resolve foreign plugin rules.
*/

// mock resolving of rules ($PKG/rules/$NAME)
if (path === 'bpmnlint-plugin-foreign/rules/rule') {
// mock resolving of exported rules ($PKG.rules[$NAME])
if (path === 'bpmnlint-plugin-foreign') {
return {
rules: {
exported: {
path: 'bpmnlint-plugin-foreign/lib/rules/exported'
}
}
};
}

// mock resolving of non-exported rules ($PKG/rules/$NAME)
if (path === 'bpmnlint-plugin-foreign/rules/non-exported') {
return {
path
};
Expand Down Expand Up @@ -96,15 +118,32 @@ describe('resolver/node-resolver', function() {

describe('plugin - foreign', function() {

it('should resolve ($PKG/rules/$NAME)', async function() {
describe('should resolve', function() {

// when
const resolvedRule = await resolver.resolveRule('bpmnlint-plugin-foreign', 'rule');
it('exported ($PKG.rules[$NAME])', async function() {

// when
const resolvedRule = await resolver.resolveRule('bpmnlint-plugin-foreign', 'exported');

// then
expect(resolvedRule).to.eql({
path: 'bpmnlint-plugin-foreign/lib/rules/exported'
});

// then
expect(resolvedRule).to.eql({
path: 'bpmnlint-plugin-foreign/rules/rule'
});


it('non-exported ($PKG/rules/$NAME)', async function() {

// when
const resolvedRule = await resolver.resolveRule('bpmnlint-plugin-foreign', 'non-exported');

// then
expect(resolvedRule).to.eql({
path: 'bpmnlint-plugin-foreign/rules/non-exported'
});
});

});


Expand Down Expand Up @@ -152,15 +191,31 @@ describe('resolver/node-resolver', function() {

describe('plugin - local', function() {

it('should resolve ($PKG/rules/$NAME)', async function() {
describe('should resolve', function() {

// when
const resolvedRule = await resolver.resolveRule('bpmnlint-plugin-local', 'rule');
it('exported ($PKG.rules[$NAME])', async function() {

// then
expect(resolvedRule).to.eql({
path: './rules/rule'
// when
const resolvedRule = await resolver.resolveRule('bpmnlint-plugin-local', 'exported');

// then
expect(resolvedRule).to.eql({
path: './lib/rules/exported'
});
});


it('non-exported ($PKG/rules/$NAME)', async function() {

// when
const resolvedRule = await resolver.resolveRule('bpmnlint-plugin-local', 'non-exported');

// then
expect(resolvedRule).to.eql({
path: './rules/non-exported'
});
});

});


Expand Down
94 changes: 69 additions & 25 deletions test/spec/support/compile-config-spec.js
Expand Up @@ -67,39 +67,83 @@ describe('support/compile-config', function() {
});


it('should import local', async function() {
describe('plugins', function() {

it('should import exported and non-exported', async function() {

// given
const resolver = new NodeResolver({
require: function(path) {
if (path === 'bpmnlint-plugin-foreign') {
return {
configs: {
recommended: {
rules: {
'exported': 'error',
'non-exported': 'error'
}
}
},
rules: {
'exported': () => {}
}
};
}

throw new Error('not found');
}
});

// given
const resolver = new NodeResolver({
require: function(path) {

if (path === './package.json') {
return {
name: 'bpmnlint-plugin-local'
};
}
// when
const code = await compileConfig({
extends: 'plugin:foreign/recommended'
}, resolver);

if (path === './config/recommended') {
return {
rules: {
'foo': 'error'
}
};
}
// then
expect(code).to.contain('import exports_0 from \'bpmnlint-plugin-foreign\'');
expect(code).to.contain('cache[\'bpmnlint-plugin-foreign/exported\'] = exports_0.rules[\'exported\']');

throw new Error('not found');
}
expect(code).to.contain('import rule_1 from \'bpmnlint-plugin-foreign/rules/non-exported\'');
expect(code).to.contain('cache[\'bpmnlint-plugin-foreign/non-exported\'] = rule_1');
});


// when
const code = await compileConfig({
extends: 'plugin:local/recommended'
}, resolver);
it('should import local', async function() {

// given
const resolver = new NodeResolver({
require: function(path) {

if (path === './package.json') {
return {
name: 'bpmnlint-plugin-local'
};
}

if (path === './config/recommended') {
return {
rules: {
'foo': 'error'
}
};
}

throw new Error('not found');
}
});


// when
const code = await compileConfig({
extends: 'plugin:local/recommended'
}, resolver);

// then
expect(code).to.contain('import rule_0 from \'./rules/foo\'');
expect(code).to.contain('cache[\'bpmnlint-plugin-local/foo\'] = rule_0');
});

// then
expect(code).to.contain('import rule_0 from \'./rules/foo\'');
expect(code).to.contain('cache[\'bpmnlint-plugin-local/foo\'] = rule_0');
});


Expand Down

0 comments on commit c19c638

Please sign in to comment.