resin-lint
Version:
Resin.io coffeelint & coffeescope2 wrapper
465 lines • 22 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs");
var glob = require("glob");
var optimist = require("optimist");
var path = require("path");
var tslint = require("tslint");
var util_1 = require("util");
var realpathAsync = util_1.promisify(fs.realpath);
var readFileAsync = util_1.promisify(fs.readFile);
var accessAsync = util_1.promisify(fs.access);
var statAsync = util_1.promisify(fs.stat);
var writeFileAsync = util_1.promisify(fs.writeFile);
var existsAsync = function (filename) { return __awaiter(void 0, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
return [4, accessAsync(filename)];
case 1:
_b.sent();
return [2, true];
case 2:
_a = _b.sent();
return [2, false];
case 3: return [2];
}
});
}); };
var globAsync = util_1.promisify(glob);
var configurations = {
coffeescript: {
configPath: path.join(__dirname, '../config/coffeelint.json'),
configFileName: 'coffeelint.json',
extensions: ['coffee'],
lang: 'coffeescript',
},
typescript: {
configPath: path.join(__dirname, '../config/tslint.json'),
configFileName: 'tslint.json',
extensions: ['ts', 'tsx'],
lang: 'typescript',
},
typescriptPrettier: {
configPath: path.join(__dirname, '../config/tslint-prettier.json'),
configFileName: 'tslint.json',
extensions: ['ts', 'tsx'],
lang: 'typescript',
},
};
var prettierConfigPath = path.join(__dirname, '../config/.prettierrc');
var getPackageJsonDir = function (dir) { return __awaiter(void 0, void 0, void 0, function () {
var name;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, findFile('package.json', dir)];
case 1:
name = _a.sent();
if (name === null) {
throw new Error('Could not find package.json!');
}
return [2, path.dirname(name)];
}
});
}); };
var read = function (filepath) { return __awaiter(void 0, void 0, void 0, function () {
var realPath;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, realpathAsync(filepath)];
case 1:
realPath = _a.sent();
return [2, readFileAsync(realPath, 'utf8')];
}
});
}); };
var findFile = function (name, dir) { return __awaiter(void 0, void 0, void 0, function () {
var filename, parent;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
dir = dir || process.cwd();
filename = path.join(dir, name);
return [4, existsAsync(filename)];
case 1:
if (_a.sent()) {
return [2, filename];
}
parent = path.dirname(dir);
if (dir === parent) {
return [2, null];
}
return [2, findFile(name, parent)];
}
});
}); };
var parseJSON = function (file) { return __awaiter(void 0, void 0, void 0, function () {
var _a, _b, err_1;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_c.trys.push([0, 2, , 3]);
_b = (_a = JSON).parse;
return [4, readFileAsync(file, 'utf8')];
case 1: return [2, _b.apply(_a, [_c.sent()])];
case 2:
err_1 = _c.sent();
console.error("Could not parse " + file);
throw err_1;
case 3: return [2];
}
});
}); };
var findFiles = function (extensions, paths) {
if (paths === void 0) { paths = []; }
return __awaiter(void 0, void 0, void 0, function () {
var files;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
files = [];
return [4, Promise.all(paths.map(function (p) { return __awaiter(void 0, void 0, void 0, function () {
var _a, _b, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0: return [4, statAsync(p)];
case 1:
if (!(_d.sent()).isDirectory()) return [3, 3];
_b = (_a = files.push).apply;
_c = [files];
return [4, globAsync(p + "/**/*.@(" + extensions.join('|') + ")")];
case 2:
_b.apply(_a, _c.concat([(_d.sent())]));
return [3, 4];
case 3:
files.push(p);
_d.label = 4;
case 4: return [2];
}
});
}); }))];
case 1:
_a.sent();
return [2, files.map(function (p) { return path.join(p); })];
}
});
});
};
var lintCoffeeFiles = function (files, config) { return __awaiter(void 0, void 0, void 0, function () {
var coffeelint, errorReport, reporter, report;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
coffeelint = require('coffeelint');
errorReport = new coffeelint.getErrorReport();
return [4, Promise.all(files.map(function (file) { return __awaiter(void 0, void 0, void 0, function () {
var source;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, read(file)];
case 1:
source = _a.sent();
errorReport.lint(file, source, config);
return [2];
}
});
}); }))];
case 1:
_a.sent();
reporter = require('coffeelint/lib/reporters/default');
report = new reporter(errorReport, {
colorize: process.stdout.isTTY,
quiet: false,
});
report.publish();
return [2, errorReport.getExitCode()];
}
});
}); };
var lintTsFiles = function (files, config, prettierConfig, autoFix) {
return __awaiter(this, void 0, void 0, function () {
var prettier, _a, linter, exitCodes, failureCode, errorReport;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!prettierConfig) return [3, 2];
return [4, Promise.resolve().then(function () { return require('prettier'); })];
case 1:
_a = _b.sent();
return [3, 3];
case 2:
_a = undefined;
_b.label = 3;
case 3:
prettier = _a;
linter = new tslint.Linter({
fix: autoFix,
formatter: 'stylish',
});
return [4, Promise.all(files.map(function (file) { return __awaiter(_this, void 0, void 0, function () {
var source, newSource, isPrettified;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, read(file)];
case 1:
source = _a.sent();
linter.lint(file, source, config);
if (!prettier) return [3, 5];
if (!autoFix) return [3, 4];
newSource = prettier.format(source, prettierConfig);
if (!(source !== newSource)) return [3, 3];
source = newSource;
return [4, writeFileAsync(file, source)];
case 2:
_a.sent();
_a.label = 3;
case 3: return [3, 5];
case 4:
isPrettified = prettier.check(source, prettierConfig);
if (!isPrettified) {
console.log("Error: File " + file + " hasn't been formatted with prettier");
return [2, 1];
}
_a.label = 5;
case 5: return [2, 0];
}
});
}); }))];
case 4:
exitCodes = _b.sent();
failureCode = exitCodes.find(function (exitCode) { return exitCode !== 0; });
if (failureCode) {
return [2, failureCode];
}
errorReport = linter.getResult();
console.log(linter.getResult().output);
return [2, errorReport.errorCount === 0 ? 0 : 1];
}
});
});
};
var lintMochaTestFiles = function (files) {
return __awaiter(this, void 0, void 0, function () {
var lintMochaTests, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, Promise.resolve().then(function () { return require('./mocha-tests-lint'); })];
case 1:
lintMochaTests = (_a.sent()).lintMochaTests;
return [4, lintMochaTests(files)];
case 2:
res = _a.sent();
if (res.isError) {
console.error('Mocha tests check FAILED!');
console.error(res.message);
return [2, 1];
}
return [2, 0];
}
});
});
};
var runLint = function (resinLintConfig, paths, config, autoFix) {
return __awaiter(this, void 0, void 0, function () {
var linterExitCode, scripts, prettierConfig, testsExitCode;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, findFiles(resinLintConfig.extensions, paths)];
case 1:
scripts = _a.sent();
if (!(resinLintConfig.lang === 'typescript')) return [3, 5];
prettierConfig = void 0;
if (!resinLintConfig.prettierCheck) return [3, 3];
return [4, parseJSON(prettierConfigPath)];
case 2:
prettierConfig = (_a.sent());
prettierConfig.parser = 'typescript';
_a.label = 3;
case 3: return [4, lintTsFiles(scripts, config, prettierConfig, autoFix)];
case 4:
linterExitCode = _a.sent();
_a.label = 5;
case 5:
if (!(resinLintConfig.lang === 'coffeescript')) return [3, 7];
return [4, lintCoffeeFiles(scripts, config)];
case 6:
linterExitCode = _a.sent();
_a.label = 7;
case 7:
if (!resinLintConfig.testsCheck) return [3, 9];
return [4, lintMochaTestFiles(scripts)];
case 8:
testsExitCode = _a.sent();
if (linterExitCode === 0) {
linterExitCode = testsExitCode;
}
_a.label = 9;
case 9:
process.on('exit', function () { return process.exit(linterExitCode); });
return [2];
}
});
});
};
exports.lint = function (passedParams) { return __awaiter(void 0, void 0, void 0, function () {
var options, depcheck_1, configOverridePath, prettierCheck, testsCheck, typescriptCheck, autoFix, resinLintConfiguration, _a, _b, config, _c, configOverride, configOverride, merge, paths;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
options = optimist(passedParams)
.usage('Usage: resin-lint [options] [...]')
.describe('f', 'Specify a linting config file to extend and override resin-lint rules')
.describe('p', 'Print default resin-lint linting rules')
.describe('i', 'Ignore linting config files in project directory and its parents')
.boolean('typescript', 'Lint typescript files instead of coffeescript')
.boolean('fix', 'Attempt to automatically fix lint errors')
.boolean('no-prettier', 'Disables the prettier code format checks')
.boolean('tests', 'Treat input files as test sources to perform extra relevant checks')
.boolean('u', 'Run unused import check');
if (options.argv._.length < 1 && !options.argv.p) {
options.showHelp();
process.exit(1);
}
if (!options.argv.u) return [3, 3];
return [4, Promise.resolve().then(function () { return require('depcheck'); })];
case 1:
depcheck_1 = _d.sent();
return [4, Promise.all(options.argv._.map(function (dir) { return __awaiter(void 0, void 0, void 0, function () {
var dependencies, _i, dependencies_1, dep;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, getPackageJsonDir(dir)];
case 1:
dir = _a.sent();
return [4, depcheck_1(path.resolve('./', dir), {
ignoreMatches: [
'@types/*',
'supervisor',
'coffee-script',
'coffeescript',
'colors',
'coffeescope2',
],
})];
case 2:
dependencies = (_a.sent()).dependencies;
if (dependencies.length > 0) {
console.log(dependencies.length + " unused dependencies:");
for (_i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) {
dep = dependencies_1[_i];
console.log("\t" + dep);
}
process.exit(1);
}
console.log('No unused dependencies!');
console.log();
return [2];
}
});
}); }))];
case 2:
_d.sent();
_d.label = 3;
case 3:
prettierCheck = options.argv.prettier !== false;
testsCheck = options.argv.tests === true;
typescriptCheck = options.argv.typescript;
autoFix = options.argv.fix === true;
resinLintConfiguration = typescriptCheck
? prettierCheck
? configurations.typescriptPrettier
: configurations.typescript
: configurations.coffeescript;
if (!options.argv.p) return [3, 5];
_b = (_a = console).log;
return [4, readFileAsync(resinLintConfiguration.configPath, 'utf8')];
case 4:
_b.apply(_a, [_d.sent()]);
process.exit(0);
_d.label = 5;
case 5:
if (!typescriptCheck) return [3, 6];
_c = tslint.Configuration.loadConfigurationFromPath(resinLintConfiguration.configPath);
return [3, 8];
case 6: return [4, parseJSON(resinLintConfiguration.configPath)];
case 7:
_c = _d.sent();
_d.label = 8;
case 8:
config = _c;
if (!options.argv.f) return [3, 10];
return [4, realpathAsync(options.argv.f)];
case 9:
configOverridePath = _d.sent();
_d.label = 10;
case 10:
if (!(!options.argv.i && !configOverridePath)) return [3, 12];
return [4, findFile(resinLintConfiguration.configFileName)];
case 11:
configOverridePath = _d.sent();
_d.label = 12;
case 12:
if (!configOverridePath) return [3, 16];
if (!typescriptCheck) return [3, 13];
configOverride = tslint.Configuration.loadConfigurationFromPath(configOverridePath);
config = tslint.Configuration.extendConfigurationFile(config, configOverride);
return [3, 16];
case 13: return [4, parseJSON(configOverridePath)];
case 14:
configOverride = _d.sent();
return [4, Promise.resolve().then(function () { return require('lodash'); })];
case 15:
merge = (_d.sent()).merge;
config = merge(config, configOverride);
_d.label = 16;
case 16:
paths = options.argv._;
resinLintConfiguration.prettierCheck = prettierCheck;
resinLintConfiguration.testsCheck = testsCheck;
return [4, runLint(resinLintConfiguration, paths, config, autoFix)];
case 17:
_d.sent();
return [2];
}
});
}); };
//# sourceMappingURL=resin-lint.js.map