]> git.proxmox.com Git - pve-eslint.git/blobdiff - src/app.js
exit with error also on warnings
[pve-eslint.git] / src / app.js
index 6bfd902f539199083d736c4ae2b97ae8551faa03..3cafdf96b5d747099ec3bbfd5f791479091a5d92 100644 (file)
@@ -1,13 +1,18 @@
-(function () {
+(function() {
 'use strict';
 
+const path = require('path');
 const color = require('colors');
 const program = require('commander');
 
 program
     .usage('[options] [<file(s) ...>]')
     .option('-c, --config <configfile>', 'uses <configfile> for eslint config instead.')
-    .option('-f, --fix', 'if set, fixes will be applied.');
+    .option('-e, --extend <configfile>', 'uses <configfile> ontop of default eslint config.')
+    .option('-f, --fix', 'if set, fixes will be applied.')
+    .option('-s, --strict', 'if set, also exit uncleanly on warnings')
+    .option('--output-config', 'if set, only output the config as JSON and exit.')
+    ;
 
 program.on('--help', function() {
     console.log('');
@@ -17,11 +22,16 @@ program.on('--help', function() {
     console.log('');
 });
 
-if (process.argv.length <= 2) {
-    program.help();
+program.parse(process.argv);
+
+if (program.config && program.extend) {
+    console.error('Cannot use both, --config and --extend, at the same time!');
+    process.exit(1);
 }
 
-program.parse(process.argv);
+if (program.args.length < 1 && !program.outputConfig) {
+    program.help();
+}
 
 let paths = program.args;
 
@@ -34,7 +44,7 @@ const defaultConfig = {
        ecmaVersion: 2017,
        ecmaFeatures: {
            impliedStrict: true,
-       }
+       },
     },
     env: {
        browser: true,
@@ -52,6 +62,8 @@ const defaultConfig = {
        console: "writable",
        eslint: "writable",
        gettext: "writable",
+       proxmoxOnlineHelpInfo: "writable",
+       pveOnlineHelpInfo: "writable",
     },
     rules: {
        // from eslint:recommend, with tweaks for our source
@@ -105,7 +117,7 @@ const defaultConfig = {
        "no-unsafe-finally": "error",
        "no-unsafe-negation": "error",
        "no-unused-labels": "error",
-       "no-unused-vars": ["error", { vars: "all", args: "none" } ],
+       "no-unused-vars": ["error", { vars: "all", args: "none", varsIgnorePattern: "^(me|_.*)$" }],
        "no-useless-catch": "error",
        "no-useless-escape": "error",
        "no-with": "error",
@@ -129,16 +141,20 @@ const defaultConfig = {
        "no-caller": "error",
        "no-constructor-return": "error",
        "no-div-regex": "error",
-       "no-else-return": "error",
+       //"no-else-return": "warn", // not a real style problem, both can be OK
        "no-empty-function": "error",
        "no-eq-null": "error",
        "no-eval": "error",
        "no-extend-native": "error",
        "no-extra-bind": "error",
        "no-extra-label": "error",
-       "no-extra-parens": "error",
+       "no-extra-parens": ["error", "all", {
+           "conditionalAssign": false, // useful for if ((match = str.match(/.../))) lines
+           "enforceForArrowConditionals": false,
+           "nestedBinaryExpressions": false,
+       }],
        "no-floating-decimal": "error",
-       "no-implicit-coercion": "error",
+       "no-implicit-coercion": ["error", { allow: ["!!"] }],
        "no-implicit-globals": "error",
        "no-implied-eval": "error",
        "no-invalid-this": "error",
@@ -177,13 +193,13 @@ const defaultConfig = {
 
        // stylistic issues, only warn, most can be auto-fixed
        // those are quite opinionated...
-       "array-bracket-spacing": [ "warn", "never" ],
-       "brace-style": [ "warn", "1tbs", { allowSingleLine: true }],
-       "comma-dangle": [ "warn", "always-multiline" ], // maybe only-multiline?
+       "array-bracket-spacing": ["warn", "never"],
+       "brace-style": ["warn", "1tbs", { allowSingleLine: true }],
+       "comma-dangle": ["warn", "always-multiline"], // maybe only-multiline?
        "comma-spacing": "warn",
        "comma-style": "warn",
        "computed-property-spacing": "warn",
-       "consistent-this": [ "warn", "me" ],
+       "consistent-this": ["warn", "me"],
        "eol-last": "warn",
        "func-call-spacing": "warn",
        "func-name-matching": "warn",
@@ -191,23 +207,42 @@ const defaultConfig = {
        "key-spacing": "warn",
        "keyword-spacing": "warn",
        "linebreak-style": "warn",
-       "max-len": [ "warn", { code: 110, tabWidth: 8, ignoreComments: true, ignoreStrings: true, ignoreRegExpLiterals: true }],
+       "max-len": ["warn", { code: 110, tabWidth: 8, ignoreComments: true, ignoreStrings: true, ignoreRegExpLiterals: true }],
        "no-array-constructor": "warn",
        "no-lonely-if": "warn",
-       "no-mixed-operators": "warn",
+       "no-mixed-operators": ["warn", {
+           "groups": [
+               //["+", "-", "*", "/", "%", "**"], // assume the devs can do basic math..
+               ["&", "|", "^", "~", "<<", ">>", ">>>"],
+               ["==", "!=", "===", "!==", ">", ">=", "<", "<="],
+               ["&&", "||"],
+               ["in", "instanceof"],
+           ],
+           "allowSamePrecedence": true,
+       }],
        "no-multiple-empty-lines": "warn",
        "no-trailing-spaces": "warn",
-       "no-underscore-dangle": [ "warn", { allowAfterThis: true, }],
+       // "no-underscore-dangle": ["warn", { allowAfterThis: true }], // we use it for unused variables, like in rust
        "no-unneeded-ternary": "warn",
        "no-whitespace-before-property": "warn",
-       "object-curly-newline": "warn",
-       "object-curly-spacing": [ "warn", "always" ],
-       "operator-linebreak" : [ "warn", "after", { overrides: { "?": "after" }}],
+       "object-curly-newline": ["warn", {
+           "multiline": true,
+           //"minProperties": 2, // FIXME: enable this??
+           "consistent": true,
+       }],
+       "object-curly-spacing": ["warn", "always"],
+       "operator-linebreak": ["warn", "after", {
+           "overrides": {
+               "?": "before",
+               ":": "before",
+               "+": "ignore",
+           },
+       }],
        "padded-blocks": ["warn", "never"], // not sure ...
-       "quote-props": [ "warn", "as-needed", { keywords: true, unnecessary: false }], // does nothing, maybe deactivate unnecessary
+       "quote-props": ["warn", "as-needed", { keywords: true, unnecessary: false }], // does nothing, maybe deactivate unnecessary
        "semi": "warn",
        "semi-spacing": "warn",
-       "semi-style": "warn",
+       // "semi-style": "warn", // could be useful, but for ?: we often want to allow the ; on the next line
        "space-before-blocks": "warn",
        "space-before-function-paren": ["warn", "never"],
        "space-in-parens": "warn",
@@ -216,21 +251,33 @@ const defaultConfig = {
        "unicode-bom": "warn",
        "arrow-body-style": "warn",
        "arrow-spacing": "warn",
-       "no-confusing-arrow": "warn",
+       // "no-confusing-arrow": "warn", // can be useful to do and isn't really confusing
        "prefer-numeric-literals": "warn",
        "template-curly-spacing": "warn",
      },
 };
 
+let pathExpand = (p) => {
+    if (p.match(/^[^/]/)) {
+       p = process.cwd() + "/" + p;
+    }
+    return p;
+};
+
 let config = defaultConfig;
 if (program.config) {
-    let path = program.config;
-    if (program.config.match(/^[^/]/)) {
-       path = process.cwd() + "/" + path;
-    }
     config = {
-       extends: path
-    }
+       "extends": pathExpand(program.config),
+    };
+} else if (program.extend) {
+    config.extends = pathExpand(program.extend);
+    console.log(`Extend with path: ${config.extends}`);
+}
+
+if (program.outputConfig) {
+    let cfg = JSON.stringify(config, null, 2);
+    console.log(cfg);
+    process.exit(0);
 }
 
 const cli = new eslint.CLIEngine({
@@ -247,74 +294,72 @@ let files_ok = [];
 let fixes = 0;
 console.log('------------------------------------------------------------');
 report.results.forEach(function(result) {
-    let filename = result.filePath;
+    let filename = path.relative(process.cwd(), result.filePath);
     let msgs = result.messages;
     let max_sev = 0;
     if (!!program.fix && result.output) {
        fixes++;
     }
-    if (msgs.length > 0) {
-       console.error('[' + color.bold(filename) + ']:');
-       msgs.forEach(function(e) {
-           let msg = 'at line ' + color.bold(e.line) + ' column ' +
-                         color.bold(e.column) + ': ' + e.ruleId;
-           if (e.severity === 1) {
-               console.error(color.yellow("Warning " + msg));
-               if (max_sev < 1) {
-                   max_sev = 1;
-               }
-           } else if (e.severity === 2) {
-               console.error(color.red("Error " + msg));
-               if (exitcode < 1) {
-                   exitcode = 1;
-               }
-               if (max_sev < 2) {
-                   max_sev = 2;
-               }
-           } else {
-               console.error("Info " + msg);
-           }
-           if (e.message) {
-               console.error(e.message);
-           }
-           if (e.suggestion) {
-               console.error(e.suggestion);
+    if (msgs.length <= 0) {
+       files_ok.push(filename);
+       return;
+    }
+    console.error(`[./${color.bold(filename)}]:`);
+    msgs.forEach(function(e) {
+       if (max_sev < e.severity) {
+           max_sev = e.severity;
+       }
+       let msg = `: line ${color.bold(e.line)} col ${color.bold(e.column)}: ${e.ruleId}`;
+       if (e.severity === 1) {
+           msg = color.yellow("WARN" + msg);
+           if (exitcode < 1 && !!program.strict) {
+               exitcode = 1;
            }
-           if (!program.fix && e.fix) {
-               fixes++;
-               console.error("Could be auto-fixed");
+       } else if (e.severity === 2) {
+           msg = color.red("ERR " + msg);
+           if (exitcode < 1) {
+               exitcode = 1;
            }
-       });
-
-       if (max_sev === 1) {
-           files_warn.push(filename);
-       } else if (max_sev === 2) {
-           files_err.push(filename);
+       } else {
+           msg = "INFO" + msg;
        }
-    } else {
-       files_ok.push(filename);
-       return;
+       if (e.message) {
+           msg += ` - ${e.message}`;
+       }
+       if (!program.fix && e.fix) {
+           fixes++;
+           msg += ' (*)';
+       }
+       console.error(msg);
+       if (e.suggestion) {
+           console.error(e.suggestion);
+       }
+    });
+
+    if (max_sev === 1) {
+       files_warn.push(filename);
+    } else if (max_sev === 2) {
+       files_err.push(filename);
     }
 
     console.log('------------------------------------------------------------');
 });
 
 if (report.results.length > 1) {
-    console.log((`${color.bold(files_ok.length + files_err.length)} files:`));
+    console.log(`${color.bold(files_ok.length + files_err.length)} files:`);
     if (files_err.length > 0) {
-       console.log(color.red(`${color.bold(files_err.length)} files have Errors`));
+       console.log(color.red(` ${color.bold(files_err.length)} files have Errors`));
     }
     if (files_warn.length > 0) {
-       console.log(color.yellow(`${color.bold(files_warn.length)} files have Warnings`));
+       console.log(color.yellow(` ${color.bold(files_warn.length)} files have Warnings`));
     }
     if (files_ok.length > 0) {
-       console.log(color.green(`${color.bold(files_ok.length)} files are OK`));
+       console.log(color.green(` ${color.bold(files_ok.length)} files are OK`));
     }
-    console.log('------------------------------------------------------------');
 } else if (files_ok.length > 0) {
     console.log(color.green(`${files_ok[0]} OK`));
-    console.log('------------------------------------------------------------');
 }
+console.log('------------------------------------------------------------');
 
 if (program.fix) {
     if (fixes > 0) {
@@ -324,10 +369,9 @@ if (program.fix) {
     } else {
        console.log("No fixable Errors/Warnings found.");
     }
-} else {
-       console.log(`${color.bold(fixes)} Errors/Warnings could be auto-fixed.`);
+} else if (fixes > 0) {
+       console.log(`${color.bold(fixes)} issues marked with (*) could be auto-fixed using '--fix'.`);
 }
 
 process.exit(exitcode);
-
 }());