-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: pull out various convert steps into helper functions (#125)
This will be useful soon for a modernize-js command that uses some of those steps.
- Loading branch information
1 parent
09af9e7
commit 41dd2de
Showing
7 changed files
with
193 additions
and
153 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import prependToFile from '../util/prependToFile'; | ||
import runWithProgressBar from '../runner/runWithProgressBar'; | ||
|
||
export default async function prependCodePrefix(jsFiles, codePrefix) { | ||
await runWithProgressBar( | ||
'Adding code prefix to converted files...', jsFiles, async function(path) { | ||
await prependToFile(path, codePrefix); | ||
return {error: null}; | ||
}); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import runWithProgressBar from '../runner/runWithProgressBar'; | ||
import prependToFile from '../util/prependToFile'; | ||
|
||
export default async function prependMochaEnv(jsFiles, mochaEnvFilePattern) { | ||
let regex = new RegExp(mochaEnvFilePattern); | ||
let testFiles = jsFiles.filter(f => regex.test(f)); | ||
await runWithProgressBar( | ||
'Adding /* eslint-env mocha */ to test files...', testFiles, async function(path) { | ||
await prependToFile(path, '/* eslint-env mocha */\n'); | ||
return {error: null}; | ||
}); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { exec } from 'mz/child_process'; | ||
|
||
import runWithProgressBar from '../runner/runWithProgressBar'; | ||
import CLIError from '../util/CLIError'; | ||
import prependToFile from '../util/prependToFile'; | ||
|
||
export default async function runEslintFix(jsFiles, config) { | ||
let eslintResults = await runWithProgressBar( | ||
'Running eslint --fix on all files...', jsFiles, makeEslintFixFn(config)); | ||
for (let result of eslintResults) { | ||
for (let message of result.messages) { | ||
console.log(message); | ||
} | ||
} | ||
} | ||
|
||
export const HEADER_COMMENT_LINES = { | ||
todo: '// TODO: This file was created by bulk-decaffeinate.', | ||
fixIssues: '// Fix any style issues and re-enable lint.', | ||
sanityCheck: '// Sanity-check the conversion and remove this comment.', | ||
}; | ||
|
||
function makeEslintFixFn(config) { | ||
return async function runEslint(path) { | ||
let messages = []; | ||
|
||
// Ignore the eslint exit code; it gives useful stdout in the same format | ||
// regardless of the exit code. Also keep a 10MB buffer since sometimes | ||
// there can be a LOT of lint failures. | ||
let eslintOutputStr = (await exec( | ||
`${config.eslintPath} --fix --format json ${path}; :`, | ||
{maxBuffer: 10000*1024}))[0]; | ||
|
||
let ruleIds; | ||
if (eslintOutputStr.includes("ESLint couldn't find a configuration file")) { | ||
messages.push(`Skipping "eslint --fix" on ${path} because there was no eslint config file.`); | ||
ruleIds = []; | ||
} else { | ||
let eslintOutput; | ||
try { | ||
eslintOutput = JSON.parse(eslintOutputStr); | ||
} catch (e) { | ||
throw new CLIError(`Error while running eslint:\n${eslintOutputStr}`); | ||
} | ||
ruleIds = eslintOutput[0].messages | ||
.map(message => message.ruleId).filter(ruleId => ruleId); | ||
ruleIds = Array.from(new Set(ruleIds)).sort(); | ||
} | ||
|
||
await prependToFile(`${path}`, `\ | ||
${HEADER_COMMENT_LINES.todo} | ||
${ruleIds.length > 0 ? HEADER_COMMENT_LINES.fixIssues : HEADER_COMMENT_LINES.sanityCheck} | ||
`); | ||
if (ruleIds.length > 0) { | ||
await prependToFile(`${path}`, `\ | ||
/* eslint-disable | ||
${ruleIds.map(ruleId => ` ${ruleId},`).join('\n')} | ||
*/ | ||
`); | ||
} | ||
return {error: null, messages}; | ||
}; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* Runs the fix-imports step on all specified JS files, and return an array of | ||
* the files that changed. | ||
*/ | ||
import { readFile } from 'fs-promise'; | ||
import { basename, join, relative, resolve } from 'path'; | ||
import zlib from 'zlib'; | ||
|
||
import runWithProgressBar from '../runner/runWithProgressBar'; | ||
import execLive from '../util/execLive'; | ||
import getFilesUnderPath from '../util/getFilesUnderPath'; | ||
|
||
export default async function runFixImports(jsFiles, config) { | ||
let {searchPath, absoluteImportPaths} = config.fixImportsConfig; | ||
if (!absoluteImportPaths) { | ||
absoluteImportPaths = []; | ||
} | ||
let scriptPath = join(__dirname, '../jscodeshift-scripts-dist/fix-imports.js'); | ||
|
||
let options = { | ||
convertedFiles: jsFiles.map(p => resolve(p)), | ||
absoluteImportPaths: absoluteImportPaths.map(p => resolve(p)), | ||
}; | ||
let eligibleFixImportsFiles = await getEligibleFixImportsFiles(searchPath, jsFiles); | ||
console.log('Fixing any imports across the whole codebase...'); | ||
if (eligibleFixImportsFiles.length > 0) { | ||
// Note that the args can get really long, so we take reasonable steps to | ||
// reduce the chance of hitting the system limit on arg length | ||
// (256K by default on Mac). | ||
let eligibleRelativePaths = eligibleFixImportsFiles.map(p => relative('', p)); | ||
let encodedOptions = zlib.deflateSync(JSON.stringify(options)).toString('base64'); | ||
await execLive(`\ | ||
${config.jscodeshiftPath} --parser flow -t ${scriptPath} \ | ||
${eligibleRelativePaths.join(' ')} --encoded-options=${encodedOptions}`); | ||
} | ||
return eligibleFixImportsFiles; | ||
} | ||
|
||
async function getEligibleFixImportsFiles(searchPath, jsFiles) { | ||
let jsBasenames = jsFiles.map(p => basename(p, '.js')); | ||
let resolvedPaths = jsFiles.map(p => resolve(p)); | ||
let allJsFiles = await getFilesUnderPath(searchPath, p => p.endsWith('.js')); | ||
await runWithProgressBar( | ||
'Searching for files that may need to have updated imports...', | ||
allJsFiles, | ||
async function(p) { | ||
let resolvedPath = resolve(p); | ||
if (resolvedPaths.includes(resolvedPath)) { | ||
return {error: null}; | ||
} | ||
let contents = (await readFile(resolvedPath)).toString(); | ||
for (let jsBasename of jsBasenames) { | ||
if (contents.includes(jsBasename)) { | ||
resolvedPaths.push(resolvedPath); | ||
return {error: null}; | ||
} | ||
} | ||
return {error: null}; | ||
}); | ||
return resolvedPaths; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { join, relative } from 'path'; | ||
|
||
import execLive from '../util/execLive'; | ||
|
||
export default async function runJscodeshiftScripts(jsFiles, config) { | ||
for (let scriptPath of config.jscodeshiftScripts) { | ||
let resolvedPath = resolveJscodeshiftScriptPath(scriptPath); | ||
console.log(`Running jscodeshift script ${resolvedPath}...`); | ||
await execLive(`${config.jscodeshiftPath} --parser flow \ | ||
-t ${resolvedPath} ${jsFiles.map(p => relative('', p)).join(' ')}`); | ||
} | ||
} | ||
|
||
function resolveJscodeshiftScriptPath(scriptPath) { | ||
if ([ | ||
'prefer-function-declarations.js', | ||
'remove-coffee-from-imports.js', | ||
'top-level-this-to-exports.js', | ||
].includes(scriptPath)) { | ||
return join(__dirname, `../jscodeshift-scripts-dist/${scriptPath}`); | ||
} | ||
return scriptPath; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { readFile, writeFile } from 'fs-promise'; | ||
|
||
export default async function prependToFile(path, prependText) { | ||
let contents = await readFile(path); | ||
let lines = contents.toString().split('\n'); | ||
if (lines[0] && lines[0].startsWith('#!')) { | ||
contents = lines[0] + '\n' + prependText + lines.slice(1).join('\n'); | ||
} else { | ||
contents = prependText + contents; | ||
} | ||
await writeFile(path, contents); | ||
} |