UNPKG

@seadub/clang-format-lint

Version:

Validate and/or fix formatting of files via clang-format

72 lines (63 loc) 2.19 kB
#!/usr/bin/env node 'use strict'; const clangFormat = require('clang-format'); const pLimit = require('p-limit'); /** * * @param {string} filepath * @param {boolean} fix * @returns {Promise<undefined|Error>} */ function lintFile(filepath, fix) { return new Promise((resolve, reject) => { let stdout = ''; const args = [ '-style=file' ]; if (fix) { args.push('-i'); } else { args.push('-output-replacements-xml'); } args.push(filepath); const proc = clangFormat.spawnClangFormat(args, () => {}, 'pipe'); proc.stdout.on('data', function (data) { stdout += data.toString(); }); proc.on('close', function (exit) { if (exit) { // Should we be rejecting if the exit code is non-zero? It'll stop processing *all* files return reject(new Error(`Failed to execute clang-format on ${filepath}. Exit code: ${exit}`)); } if (fix) { return resolve(); } // doing validation... const modified = stdout.replace(/\r?\n/g, ''); if (modified !== '<?xml version=\'1.0\'?><replacements xml:space=\'preserve\' incomplete_format=\'false\'></replacements>') { // Record failure, because formatting is bad. // TODO Get the correctly formatted source? Give more details on the bad sections? // Instead of rejecting, resolve with the error - so we ensure every file gets processed! resolve(new Error(`Formatting incorrect on "${filepath}", proposed changes: ${stdout}`)); } resolve(); }); }); } /** * @param {string[]} files list of filepaths to validate/fix * @param {integer} execLimit maximum number of files to process simultaneously * @param {boolean} [fix=false] automatically fix the files? * @throws {Error} if any files failed validation */ async function main(files, execLimit, fix = false) { const limit = pLimit(execLimit); const promises = files.map(file => limit(lintFile, file, fix)); const results = await Promise.all(promises); // filter results to ones containing Error instances const errors = results.filter(r => r instanceof Error); if (errors.length > 0) { const error = new Error(errors.join('\n')); error.code = 'ELINTFAILURE'; throw error; } } module.exports = main;