Repository: jshint/jshint (js)

Issue:
showing Error (E043) on "Too many errors", when those "Errors" are only warnings
There should be a separate counter for warnings and for errors.
And separate giving up actions and messages: "Too many Errors" and "Too many Warnings"

I came accross two cases where this is specially important.

I use `debug['something']` throughout the code. There is a reason for that and it's valid. I hid the warning. Not by jshint options. Now all I see is one error saying there is too many errors.
It was quite a time-waster issue finding out what was going on.

Yes, I tried // jshint -W069 instead and the error was not there anymore, probably warnings hidden by jshint options are not counted.
But it does not mean that the logic of a common counter is ok.
Many times jshint is not used directly and warnings could be hidden upstream.


A lot of scripts use jshint to check user-added scripts for errors before executing them in its environment.
They should be set to ignore all warnings or set the maxerr too high. Tamper Monkey seems to be doing that. But it is not something to be expected naturally.

There is a closed issue: https://github.com/jshint/jshint/issues/180,
but the proposed solutions were to remove the feature, or make it opt-in.

What I mean here is that the feature itself is not an issue, but joining counts of warnings and errors and reacting with one common action is.


Pull request description:
[[FIX]] Limit "Too many Errors" (E043) to errors only
As mentioned in #3444 , `E043` is triggered with "Too many Errors" even if there are just warnings in the checked code. This happens because the condition to trigger the said `E043` error is:

```
if (JSHINT.errors.length >= state.option.maxerr)
      quit("E043", t);
```
Which clearly checks for the total count of all the messages in `JSHINT.errors` array, The issue is that, this array not only contains errors but also warnings and informative messages. This makes the `E043` run even if there are no errors but only warnings exceeding the count defined in `maxerr` config.

This PR will modify the condition for running into `E043`, by ignoring all warnings and other messages and considering only errors.

This also updates the `maxerr` documentation to reflect the above change.

The tests changed to accommodate for the new behavior are:

1.  `core.js:testRawOnError`

    "Too many errors." is no longer being thrown because "Unnecessary semicolon" is a warning (`W032`)

2. `core.js:insideEval`
    Similar case of "Too many errors." not triggering (`maxerr` is set to 1 here) as "eval can be harmful." is a warning (`W061`)

3. `parser.js:restOperatorWithoutIdentifier`
    We run into "Too many errors." at `9:22` now instead of `8:30` because the warnings in between are no longer considered.

This PR closes #3444 

Patch:
diff --git a/src/jshint.js b/src/jshint.js
index f409c061..c0da0e97 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -423,9 +423,10 @@ var JSHINT = (function() {
 
     removeIgnoredMessages();
 
-    if (JSHINT.errors.length >= state.option.maxerr)
+    var errors = JSHINT.errors.filter(function(e) { return /E\d{3}/.test(e.code); });
+    if (errors.length >= state.option.maxerr) {
       quit("E043", t);
-
+    }
     return w;
   }
 
diff --git a/src/options.js b/src/options.js
index 482575ea..8e622296 100644
--- a/src/options.js
+++ b/src/options.js
@@ -820,7 +820,7 @@ exports.val = {
   indent       : false,
 
   /**
-   * This options allows you to set the maximum amount of warnings JSHint will
+   * This options allows you to set the maximum amount of errors JSHint will
    * produce before giving up. Default is 50.
    */
   maxerr       : false,


Test patch:
diff --git a/tests/unit/core.js b/tests/unit/core.js
index 0d989788..b0e8a4b1 100644
--- a/tests/unit/core.js
+++ b/tests/unit/core.js
@@ -421,9 +421,17 @@ exports.argsInCatchReused = function (test) {
   test.done();
 };
 
-exports.testRawOnError = function (test) {
+exports.testRawOnWarning = function (test) {
   JSHINT(';', { maxerr: 1 });
   test.equal(JSHINT.errors[0].raw, 'Unnecessary semicolon.');
+  test.equal(JSHINT.errors[1], null);
+
+  test.done();
+};
+
+exports.testRawOnError = function (test) {
+  JSHINT('@', { maxerr: 1 });
+  test.equal(JSHINT.errors[0].raw, 'Unexpected \'{a}\'.');
   test.equal(JSHINT.errors[1].raw, 'Too many errors.');
   test.equal(JSHINT.errors[2], null);
 
@@ -472,12 +480,6 @@ exports.insideEval = function (test) {
 
     .test(src, { es3: true, evil: false });
 
-  // Regression test for bug GH-714.
-  JSHINT(src, { evil: false, maxerr: 1 });
-  var err = JSHINT.data().errors[1];
-  test.equal(err.raw, "Too many errors.");
-  test.equal(err.scope, "(main)");
-
   test.done();
 };
 
diff --git a/tests/unit/parser.js b/tests/unit/parser.js
index 96928580..e045296a 100644
--- a/tests/unit/parser.js
+++ b/tests/unit/parser.js
@@ -9142,7 +9142,14 @@ exports.restOperatorWithoutIdentifier = function (test) {
     .addError(8, 24, "Expected an identifier and instead saw ')'.")
     .addError(8, 26, "Expected ',' and instead saw '=>'.")
     .addError(8, 30, "Expected ',' and instead saw ';'.")
-    .addError(8, 30, "Too many errors. (44% scanned).")
+    .addError(9, 1, "Expected an identifier and instead saw 'var' (a reserved word).")
+    .addError(9, 5, "Expected ',' and instead saw 'arrow3'.")
+    .addError(9, 12, "Expected an identifier and instead saw '='.")
+    .addError(9, 14, "Expected ',' and instead saw '('.")
+    .addError(9, 19, "Expected an identifier and instead saw ']'.")
+    .addError(9, 20, "Expected ',' and instead saw ')'.")
+    .addError(9, 22, "Expected an identifier and instead saw '=>'.")
+    .addError(9, 22, "Too many errors. (50% scanned).")
     .test(code, { esnext: true });
 
   test.done();