Repository: jshint/jshint
Pull request #3397 (2019-05-05 21:14:54)

[[TEST]] Improve coverage
Add test for handling of invalid ImportsList (without the branch under
test, no error would be reported when ImportSpecifiers are not
delineated by a comma).

coveralls: 
[![Coverage Status](https://coveralls.io/builds/23200995/badge)](https://coveralls.io/builds/23200995)

Coverage remained the same at 100.0% when pulling **27998ab5d4f941462aaa8ec58448f2a53d38a971 on jugglinmike:coverage-import** into **02f20b23bafb1aacbde41bfcdafe23e419c955d3 on jshint:master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/23200995/badge)](https://coveralls.io/builds/23200995)

Coverage remained the same at 100.0% when pulling **27998ab5d4f941462aaa8ec58448f2a53d38a971 on jugglinmike:coverage-import** into **02f20b23bafb1aacbde41bfcdafe23e419c955d3 on jshint:master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/23200995/badge)](https://coveralls.io/builds/23200995)

Coverage remained the same at 100.0% when pulling **27998ab5d4f941462aaa8ec58448f2a53d38a971 on jugglinmike:coverage-import** into **02f20b23bafb1aacbde41bfcdafe23e419c955d3 on jshint:master**.


Patch:
diff --git a/src/jshint.js b/src/jshint.js
index cd88e19e..c1bb4ae7 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -3173,6 +3173,12 @@ var JSHINT = (function() {
       ret = first = last = exprs[0];
 
       if (!isNecessary) {
+        // async functions are identified after parsing due to the complexity
+        // of disambiguating the `async` keyword.
+        if (!triggerFnExpr) {
+          triggerFnExpr = ret.id === "async";
+        }
+
         isNecessary =
           // Used to distinguish from an ExpressionStatement which may not
           // begin with the `{` and `function` tokens
@@ -5292,7 +5298,7 @@ var JSHINT = (function() {
         error("E024", this, "await");
       }
 
-      expression(context, 0);
+      expression(context, 10);
       return this;
     } else {
       this.exps = false;
@@ -5549,9 +5555,7 @@ var JSHINT = (function() {
           advance("}");
           break;
         } else {
-          /* istanbul ignore next */
           error("E024", state.tokens.next, state.tokens.next.value);
-          /* istanbul ignore next */
           break;
         }
       }


Test patch:
diff --git a/tests/unit/core.js b/tests/unit/core.js
index 1946e475..2ebb3c72 100644
--- a/tests/unit/core.js
+++ b/tests/unit/core.js
@@ -928,6 +928,19 @@ exports.testES6Modules = function (test) {
       "import afterLabelImported from 'elsewhere';"
     ], { esversion: 6 });
 
+  TestRun(test, "invalid ImportsList")
+    .addError(1, 12, "Unexpected 'y'.")
+    .addError(1, 12, "Expected 'from' and instead saw 'y'.")
+    .addError(1, 14, "Expected '(string)' and instead saw '}'.")
+    .addError(1, 15, "Missing semicolon.")
+    .addError(1, 16, "Expected an assignment or function call and instead saw an expression.")
+    .addError(1, 20, "Missing semicolon.")
+    .addError(1, 21, "Expected an assignment or function call and instead saw an expression.")
+    .addError(1, 16, "'from' is not defined.")
+    .test([
+      "import { x y } from 'elsewhere';"
+    ], { esversion: 6, module: true });
+
   TestRun(test, "async as Identifier")
     .test([
       "var async;",
diff --git a/tests/unit/options.js b/tests/unit/options.js
index ece32ae7..2f91f57e 100644
--- a/tests/unit/options.js
+++ b/tests/unit/options.js
@@ -3425,6 +3425,86 @@ singleGroups.exponentiation = function (test) {
   test.done();
 };
 
+singleGroups.asyncFunction = function (test) {
+  TestRun(test, "Async Function Expression")
+    .test([
+      "(async function() {})();",
+      "(async function a() {})();"
+    ], { singleGroups: true, esversion: 8 });
+
+  TestRun(test, "Async Generator Function Expression")
+    .test([
+      "(async function * () { yield; })();",
+      "(async function * a() { yield; })();"
+    ], { singleGroups: true, esversion: 9 });
+
+
+  TestRun(test, "Async Arrow Function")
+    .test([
+      "(async () => {})();",
+      "(async x => x)();"
+    ], { singleGroups: true, esversion: 8 });
+
+  TestRun(test, "async identifier")
+    .addError(1, 1, "Unnecessary grouping operator.")
+    .addError(2, 1, "Unnecessary grouping operator.")
+    .test([
+      "(async());",
+      "(async(x, y, z));"
+    ], { singleGroups: true, esversion: 8 });
+
+  test.done();
+};
+
+singleGroups.await = function (test) {
+  TestRun(test, "MultiplicativeExpression")
+    .addError(2, 3, "Unnecessary grouping operator.")
+    .test([
+      "(async function() {",
+      "  (await 2) * 3;",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  TestRun(test, "ExponentiationExpression")
+    .addError(2, 3, "Unnecessary grouping operator.")
+    .test([
+      "(async function() {",
+      "  (await 2) ** 3;",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  TestRun(test, "CallExpression")
+    .test([
+      "(async function() {",
+      "  (await 2)();",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  TestRun(test, "EqualityExpression")
+    .addError(2, 3, "Unnecessary grouping operator.")
+    .addError(3, 3, "Unnecessary grouping operator.")
+    .addError(4, 3, "Unnecessary grouping operator.")
+    .addError(5, 3, "Unnecessary grouping operator.")
+    .test([
+      "(async function() {",
+      "  (await 2) == 2;",
+      "  (await 2) != 2;",
+      "  (await 2) === 2;",
+      "  (await 2) !== 2;",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  TestRun(test, "Expression")
+    .addError(2, 3, "Unnecessary grouping operator.")
+    .test([
+      "(async function() {",
+      "  (await 0), 0;",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  test.done();
+};
+
 singleGroups.objectLiterals = function (test) {
   var code = [
     "({}).method();",
diff --git a/tests/unit/parser.js b/tests/unit/parser.js
index cf1a9284..7386f845 100644
--- a/tests/unit/parser.js
+++ b/tests/unit/parser.js
@@ -9591,6 +9591,16 @@ exports.asyncFunctions.awaitOperator = function (test) {
       "};",
     ], { esversion: 8 });
 
+  // Regression test for gh-3395
+  TestRun(test, "within object initializer")
+    .test([
+      "void async function() {",
+      "  void {",
+      "    x: await 0,",
+      "  };",
+      "};"
+    ], { esversion: 8 });
+
   test.done();
 };