Repository: jshint/jshint (js)

Issue:
Option to disallow "var" keyword with esnext: true
`esnext: true` adds support for `let` and `const` which make `var` obsolete in most cases, esp. in node.js environments. It would be great to have an option to warn about variables declared with `var` since its usage is most likely a mistake in ES6 files.

Pull request description:
[[FEAT]] add `varstmt` enforcement option to disallow use of VariableStatements
Closes #1549

Patch:
diff --git a/src/jshint.js b/src/jshint.js
index 9b5d543d..951e2299 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -178,7 +178,8 @@ var JSHINT = (function() {
   function processenforceall() {
     if (state.option.enforceall) {
       for (var enforceopt in options.bool.enforcing) {
-        if (state.option[enforceopt] === undefined) {
+        if (state.option[enforceopt] === undefined &&
+            !options.noenforceall[enforceopt]) {
           state.option[enforceopt] = true;
         }
       }
@@ -3507,6 +3508,10 @@ var JSHINT = (function() {
         break;
       }
 
+      if (state.option.varstmt) {
+        warning("W132", this);
+      }
+
       this.first = this.first.concat(names);
 
       if (state.tokens.next.id === "=") {
diff --git a/src/messages.js b/src/messages.js
index 4f11c523..7603a4b7 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -206,7 +206,8 @@ var warnings = {
   W129: "'{a}' is defined in a future version of JavaScript. Use a " +
     "different variable name to avoid migration issues.",
   W130: "Invalid element after rest element.",
-  W131: "Invalid parameter after rest parameter."
+  W131: "Invalid parameter after rest parameter.",
+  W132: "`var` declarations are forbidden. Use `let` or `const` instead."
 };
 
 var info = {
diff --git a/src/options.js b/src/options.js
index 017d2dab..b1c6f6c8 100644
--- a/src/options.js
+++ b/src/options.js
@@ -267,6 +267,16 @@ exports.bool = {
      */
     singleGroups: false,
 
+    /**
+     * When set to true, the use of VariableStatements are forbidden.
+     * For example:
+     *
+     *     // jshint varstmt: true
+     *
+     *     var a; // Warning: `var` declarations are forbidden. Use `let` or `const` instead.
+     */
+    varstmt: false,
+
     /**
      * This option is a short hand for the most strict JSHint configuration. It
      * enables all enforcing options and disables all relaxing options.
@@ -945,3 +955,9 @@ exports.removed = {
   smarttabs: true,
   trailing: true
 };
+
+// Add options here which should not be automatically enforced by
+// `enforceall`.
+exports.noenforceall = {
+  varstmt: true
+};


Test patch:
diff --git a/tests/unit/options.js b/tests/unit/options.js
index 21413d45..30b14cf0 100644
--- a/tests/unit/options.js
+++ b/tests/unit/options.js
@@ -2290,3 +2290,25 @@ exports.futureHostile = function (test) {
 
   test.done();
 };
+
+
+exports.varstmt = function (test) {
+  var code = [
+    "var x;",
+    "var y = 5;",
+    "var fn = function() {",
+    "  var x;",
+    "  var y = 5;",
+    "};"
+  ];
+
+  TestRun(test)
+    .addError(1, "`var` declarations are forbidden. Use `let` or `const` instead.")
+    .addError(2, "`var` declarations are forbidden. Use `let` or `const` instead.")
+    .addError(3, "`var` declarations are forbidden. Use `let` or `const` instead.")
+    .addError(4, "`var` declarations are forbidden. Use `let` or `const` instead.")
+    .addError(5, "`var` declarations are forbidden. Use `let` or `const` instead.")
+    .test(code, { varstmt: true });
+
+  test.done();
+};