UNPKG

resin-lint

Version:

Resin.io coffeelint & coffeescope2 wrapper

465 lines 22 kB
"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