Last active
March 11, 2016 18:21
-
-
Save pauljz/a2a45964f1494723a966 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node_modules/.bin/babel-node | |
/** | |
* This script is used to keep eslint passing as we upgrade our coding style. | |
* | |
* It will find all broken eslint rules in legacy code and automatically add eslint ignores for | |
* any rules the file breaks. It will also clean up rules that are no longer in violation. | |
* | |
* This approach lets us make sure we're writing new code strictly without needing to constantly | |
* rewrite our old code. | |
*/ | |
const fs = require('fs'); | |
const childProcess = require('child_process'); | |
const util = require('util'); | |
const ESLINT_CMD = 'node node_modules/eslint/bin/eslint.js'; | |
const PATH = 'src/javascript'; | |
const EXEC_OPTS = { | |
maxBuffer: 20 * 1024 * 1024, | |
encoding: 'utf-8' | |
}; | |
function walk(dir) { | |
let results = []; | |
fs.readdirSync(dir).forEach(file => { | |
const path = `${dir}/${file}`; | |
const stat = fs.statSync(path); | |
if (stat && stat.isDirectory()) { | |
results = results.concat(walk(path)); | |
} else { | |
results.push(path); | |
} | |
}); | |
return results; | |
} | |
function stripIgnoreRules() { | |
const allFiles = walk(PATH); | |
const jsFiles = allFiles.filter(x => x.match(/\.jsx?$/)); | |
jsFiles.forEach(f => { | |
const body = fs.readFileSync(f, { encoding: 'utf-8' }); | |
const strippedBody = body.replace(/^\/\* eslint [\s\S]*?\*\/\s+/, ''); | |
if (body !== strippedBody) { | |
fs.writeFileSync(f, strippedBody); | |
} | |
}); | |
} | |
function addIgnoreRules(f) { | |
util.log(f.filePath); | |
const ruleIds = new Set(f.messages.map(m => m.ruleId)); | |
const rules = [...ruleIds].map(x => `${x}:0`); | |
let comment = ''; | |
let ruleLine = '/* eslint '; | |
for (let i = 0; i < rules.length; i++) { | |
const suffix = (i < rules.length - 1) ? ', ' : ' */'; | |
const rule = rules[i] + suffix; | |
if (ruleLine.length + rule.length <= 100) { | |
ruleLine += rule; | |
} else { | |
comment += `${ruleLine.trimRight()}\n`; | |
ruleLine = ` ${rule}`; | |
} | |
} | |
comment += ruleLine; | |
const origBody = fs.readFileSync(f.filePath, { encoding: 'utf-8' }); | |
const newBody = `${comment}\n${origBody}`; | |
fs.writeFileSync(f.filePath, newBody); | |
} | |
function lint() { | |
const cmd = `${ESLINT_CMD} -c .eslintrc.js --ext .js --ext .jsx -f json ${PATH}`; | |
childProcess.execSync(cmd, EXEC_OPTS); | |
} | |
function applyFixes() { | |
try { | |
const cmd = `${ESLINT_CMD} -c .eslintrc.js --ext .js --ext .jsx --fix ${PATH}`; | |
childProcess.execSync(cmd, EXEC_OPTS); | |
} catch (e) { | |
// | |
} | |
} | |
function main() { | |
util.log('Stripping existing ignore rules'); | |
stripIgnoreRules(); | |
for (let pass = 1; pass <= 2; pass++) { | |
util.log(`Applying automatic fixes, pass ${pass}`); | |
applyFixes(); | |
} | |
try { | |
util.log('Linting'); | |
lint(); | |
util.log('No errors.'); | |
} catch (e) { | |
util.log('Parsing eslint output'); | |
const lintOutput = JSON.parse(e.stdout); | |
util.log('Commenting files'); | |
lintOutput.filter(f => f.messages.length > 0).forEach(addIgnoreRules); | |
util.log('Commenting complete'); | |
} | |
util.log('Confirming'); | |
try { | |
lint(); | |
util.log('Errors resolved'); | |
} catch (e) { | |
util.log('Errors remain'); | |
} | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment