Permalink
Browse files

[[FIX]] Relax singleGroups restrictions: IIFEs

Although not technically necessary, the grouping operator is commonly
used to "wrap" function expressions in cases where it is the left-hand
side of some operator (typically as the target of invocation). This
pattern affords readers a hint that the function object in question is
the target of some further operation--likely many lines after the
initial `function` keyword.

Update the behavior of the `singleGroups` option to allow for such
usages since they serve a beneficial purpose beyond modifying expression
execution order.
  • Loading branch information...
jugglinmike committed Apr 29, 2015
1 parent dd768c2 commit 9f551603e400c9ec3828a2c323aff804d6a08176
Showing with 20 additions and 28 deletions.
  1. +8 −0 src/jshint.js
  2. +12 −28 tests/unit/options.js
@@ -2626,6 +2626,14 @@ var JSHINT = (function() {
// Used to distinguish from an ExpressionStatement which may not
// begin with the `{` and `function` tokens
(opening.beginsStmt && (ret.id === "{" || triggerFnExpr || isFunctor(ret))) ||
// Used to signal that a function expression is being supplied to
// some other operator.
(triggerFnExpr &&
// For parenthesis wrapping a function expression to be considered
// necessary, the grouping operator should be the left-hand-side of
// some other operator--either within the parenthesis or directly
// following them.
(!isEndOfExpr() || state.tokens.prev.id !== "}")) ||
// Used as the return value of a single-statement arrow function
(ret.id === "{" && preceeding.id === "=>");
}
@@ -2022,10 +2022,11 @@ singleGroups.functionExpression = function (test) {
"(function() {}());",
"(function() {}.call());",
"if (true) {} (function() {}());",
"var a",
"(function() {}());",
// These usages are not technically necessary, but parenthesis are commonly
// used to signal that a function expression is going to be invoked
// immediately.
"var a = (function() {})();",
// Invalid forms:
"var b = (function() {}).call();",
"var c = (function() {}());",
"var d = (function() {}.call());",
@@ -2036,21 +2037,12 @@ singleGroups.functionExpression = function (test) {
"if ((function() {})()) {}",
"if ((function() {}).call()) {}",
"if ((function() {}())) {}",
"if ((function() {}.call())) {}"
"if ((function() {}.call())) {}",
// Invalid forms:
"var i = (function() {});"
];

TestRun(test)
.addError(8, "Unnecessary grouping operator.")
.addError(9, "Unnecessary grouping operator.")
.addError(10, "Unnecessary grouping operator.")
.addError(11, "Unnecessary grouping operator.")
.addError(12, "Unnecessary grouping operator.")
.addError(13, "Unnecessary grouping operator.")
.addError(14, "Unnecessary grouping operator.")
.addError(15, "Unnecessary grouping operator.")
.addError(16, "Unnecessary grouping operator.")
.addError(17, "Unnecessary grouping operator.")
.addError(18, "Unnecessary grouping operator.")
.addError(19, "Unnecessary grouping operator.")
.test(code, { singleGroups: true, asi: true });

@@ -2064,10 +2056,11 @@ singleGroups.generatorExpression = function (test) {
"(function*() { yield; }());",
"(function*() { yield; }.call());",
"if (true) {} (function*() { yield; }());",
"var a",
"(function*() { yield; }());",
// These usages are not technically necessary, but parenthesis are commonly
// used to signal that a function expression is going to be invoked
// immediately.
"var a = (function*() { yield; })();",
// Invalid forms:
"var b = (function*() { yield; }).call();",
"var c = (function*() { yield; }());",
"var d = (function*() { yield; }.call());",
@@ -2078,21 +2071,12 @@ singleGroups.generatorExpression = function (test) {
"if ((function*() { yield; })()) {}",
"if ((function*() { yield; }).call()) {}",
"if ((function*() { yield; }())) {}",
"if ((function*() { yield; }.call())) {}"
"if ((function*() { yield; }.call())) {}",
// Invalid forms:
"var i = (function*() { yield; });"
];

TestRun(test)
.addError(8, "Unnecessary grouping operator.")
.addError(9, "Unnecessary grouping operator.")
.addError(10, "Unnecessary grouping operator.")
.addError(11, "Unnecessary grouping operator.")
.addError(12, "Unnecessary grouping operator.")
.addError(13, "Unnecessary grouping operator.")
.addError(14, "Unnecessary grouping operator.")
.addError(15, "Unnecessary grouping operator.")
.addError(16, "Unnecessary grouping operator.")
.addError(17, "Unnecessary grouping operator.")
.addError(18, "Unnecessary grouping operator.")
.addError(19, "Unnecessary grouping operator.")
.test(code, { singleGroups: true, asi: true, esnext: true });

0 comments on commit 9f55160

Please sign in to comment.