eslint-compare-config
eslint-compare-config copied to clipboard
Can't compare configs that extend one another
If we compare A and B, where A extends B, it won't tell us which rules are redundant.
That makes sense, because it's looking at the resultant ruleset. It might work if you try the --literal
mode.
I thought that --literal
only removes the auto-discovery of .eslintrc files within directories?
Here's a script that I wrote for getting the job done:
'use strict';
// @todo replace this when possible: https://github.com/scottnonnenberg/eslint-compare-config/issues/7
const {green, grey, red, yellow} = require('chalk');
const {readFileSync} = require('fs');
const stripComments = require('strip-json-comments'); // used by eslint v4
const filterRules = (configA, configB) => {
const matching = [];
const unmatching = [];
Object.keys(configA.rules).forEach(ruleName => {
const configARule = configA.rules[ruleName];
const configBRule = configB.rules[ruleName];
const isMatchingError = isErrorRule(configARule) && isErrorRule(configBRule);
const isMatchingOff = isOffRule(configARule) && isOffRule(configBRule);
const isMatchingWarn = isWarnRule(configARule) && isWarnRule(configBRule);
if (isMatchingError || isMatchingOff || isMatchingWarn) {
matching.push(ruleName);
} else {
unmatching.push(ruleName);
}
});
return {
matching: matching.sort(),
unmatching: unmatching.sort()
};
};
const getRuleValue = rule => {
if (Array.isArray(rule)) {
return rule[0];
} else {
return rule;
}
};
const isErrorRule = rule => isRuleType(rule, 2, 'error');
const isOffRule = rule => isRuleType(rule, 0, 'off');
const isRuleType = (rule, number, string) => {
const ruleValue = getRuleValue(rule);
return ruleValue === number || ruleValue === string;
};
const isWarnRule = rule => isRuleType(rule, 1, 'warn');
const loadConfigs = () => ({
configA: JSON.parse(stripComments(readFileSync(`${__dirname}/../.eslintrc`, 'utf8'))),
configB: require('eslint/conf/eslint-recommended')
});
const run = () => {
const {configA, configB} = loadConfigs();
const {matching, unmatching} = filterRules(configA, configB);
const logRules = (rules, isMatching) => {
if (rules.length > 0) {
const matchingColor = isMatching ? green : red;
rules.forEach(ruleName => {
const configARule = getRuleValue(configA.rules[ruleName]);
const configBRule = getRuleValue(configB.rules[ruleName]);
console.log(`${yellow(ruleName)} ${grey('--')} project: ${matchingColor(configARule)}, base: ${matchingColor(configBRule)}`);
});
} else {
console.log(grey('(none)'));
}
};
console.log(grey('Comparing project .eslintrc with its base, "eslint:recommended"'));
console.log(`\nMATCHING/REDUNDANT RULES: ${grey('(didn\'t check options)')}`);
logRules(matching, true);
console.log('\nUNMATCHING RULES:');
logRules(unmatching, false);
};
run();
The --literal
option disables the code that computes the final ruleset (using both extended configs and any locally-specified rule). So in theory you could do what you're looking to do by using the --literal
mode and pointing this tool to the eslint-recommended
config you reference in that code.
But I do like this feature generally, answering the question "Are we re-declaring things already declared in a base config?"
It's very similar to one of the things I wanted to do early on with this tool, figuring out if your manually-provided values for a given rule were redundant given the defaults. It's just that I didn't have ready access to the defaults. :0/
npx eslint-compare-config --literal ./.eslintrc node_modules/eslint/conf/eslint-recommended.js
Unexpected token :
npx eslint-compare-config ./.eslintrc node_modules/eslint/conf/eslint-recommended.js --literal
Unexpected token :
Yeah, the tool doesn't support all formats eslint
supports... :0/
Please consider continuing maintenance.