|
"use strict"; |
|
|
|
const CLIEngine = require("eslint").CLIEngine; |
|
const _ = require('underscore'); |
|
const glob = require('glob'); |
|
const fs = require('fs'); |
|
const path = require('path'); |
|
|
|
const APP = path.join(__dirname, 'app'); |
|
|
|
const cli = new CLIEngine({ |
|
envs: ["browser"], |
|
// Consider .eslintrc |
|
useEslintrc: true, |
|
// Find undefined variables only. |
|
rules: { |
|
'no-undef': 2 |
|
} |
|
}); |
|
|
|
// Get filenames to process |
|
const filesToCheck = process.argv.slice(2); |
|
const report = cli.executeOnFiles(filesToCheck); |
|
|
|
// RegExp to match undefined variables from the ESLint report. |
|
// Sure, there should be a proper way to obtain variable names. |
|
const REGEXP = /\'(.+)\' is not defined\./; |
|
|
|
// Find all JavaScript files |
|
const files = glob.sync('*/*/*/*.js', { |
|
cwd: APP |
|
}); |
|
|
|
function filterNoUndef(message) { |
|
return message.ruleId === 'no-undef' && message.severity === 2 && REGEXP.test(message.message); |
|
} |
|
|
|
// Map variable name to "var <Class> = require('<path/to/Class>')" statement |
|
// in case file with such name present in the file system. |
|
// With an assumption that all "classes" are placed in files with the corresponding names. |
|
function mapToRequireStatement(objName) { |
|
var requirement = files.find(file => file.indexOf(`/${objName}.js`) > -1) || objName; |
|
return `var ${objName} = require('${requirement}');`; |
|
} |
|
|
|
/** |
|
* Map file name to object of { filePath: string, undefinedObjects: Array } |
|
* Where filePath is path to the file and |
|
* undefinedObjects is an array of "var <Class> = require('<path/to/Class>')" statements |
|
*/ |
|
function getFilePathAndFilteredMessages(file) { |
|
return { |
|
filePath: file.filePath, |
|
undefinedObjects: _.chain(file.messages) |
|
.filter(filterNoUndef) |
|
.map(message => message.message.match(REGEXP)[1]) |
|
.uniq() |
|
.map(mapToRequireStatement) |
|
.value() |
|
}; |
|
} |
|
|
|
// We've instructed ESLint to produce errors on undefined variables only |
|
const results = CLIEngine.getErrorResults(report.results) |
|
.map(getFilePathAndFilteredMessages) |
|
// Drop results with no undefined variables |
|
.filter(file => file.undefinedObjects.length > 0); |
|
|
|
// Prepend require('') to files |
|
results.forEach(result => { |
|
var data = fs.readFileSync(result.filePath); |
|
var fd = fs.openSync(result.filePath, 'w+'); |
|
|
|
// Construct a string of array of newly created require() statements |
|
var buffer = new Buffer(result.undefinedObjects.join('\n') + '\n\n'); |
|
// Prepend require() statements to the file |
|
fs.writeSync(fd, buffer, 0, buffer.length); |
|
// Append the rest of file |
|
fs.appendFileSync(fd, data); |
|
|
|
fs.close(fd); |
|
}); |