Skip to content

Commit

Permalink
Fixed #1311: Add support for destructuring function parameters (PR #1450
Browse files Browse the repository at this point in the history
)

Signed-off-by: Anton Kovalyov <anton@kovalyov.net>
  • Loading branch information
arai-a authored and valueof committed Jan 26, 2014
1 parent 61cc5e5 commit 9189c74
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/jshint.js
Expand Up @@ -2572,13 +2572,22 @@ var JSHINT = (function () {
var bracket, brackets = []; var bracket, brackets = [];
var pn, pn1, i = 0; var pn, pn1, i = 0;
var ret; var ret;
var parens = 1;


do { do {
pn = peek(i); pn = peek(i);

if (pn.value === "(") {
parens += 1;
} else if (pn.value === ")") {
parens -= 1;
}

i += 1; i += 1;
pn1 = peek(i); pn1 = peek(i);
i += 1; i += 1;
} while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)"); } while (!(parens === 0 && pn.value === ")") &&
pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");


if (state.tokens.next.id === "function") { if (state.tokens.next.id === "function") {
state.tokens.next.immed = true; state.tokens.next.immed = true;
Expand All @@ -2588,7 +2597,7 @@ var JSHINT = (function () {


if (state.tokens.next.id !== ")") { if (state.tokens.next.id !== ")") {
for (;;) { for (;;) {
if (pn1.value === "=>" && state.tokens.next.value === "{") { if (pn1.value === "=>" && _.contains(["{", "["], state.tokens.next.value)) {
bracket = state.tokens.next; bracket = state.tokens.next;
bracket.left = destructuringExpression(); bracket.left = destructuringExpression();
brackets.push(bracket); brackets.push(bracket);
Expand Down Expand Up @@ -2801,7 +2810,7 @@ var JSHINT = (function () {
if (_.contains(["{", "["], curr.id)) { if (_.contains(["{", "["], curr.id)) {
for (t in curr.left) { for (t in curr.left) {
t = tokens[t]; t = tokens[t];
if (t.id) { if (t && t.id) {
params.push(t.id); params.push(t.id);
addlabel(t.id, { type: "unused", token: t.token }); addlabel(t.id, { type: "unused", token: t.token });
} }
Expand All @@ -2811,7 +2820,7 @@ var JSHINT = (function () {
warning("W104", curr, "spread/rest operator"); warning("W104", curr, "spread/rest operator");
} }
continue; continue;
} else { } else if (curr.value !== ",") {
params.push(curr.value); params.push(curr.value);
addlabel(curr.value, { type: "unused", token: curr }); addlabel(curr.value, { type: "unused", token: curr });
} }
Expand Down Expand Up @@ -3299,6 +3308,10 @@ var JSHINT = (function () {
} }
} else if (state.tokens.next.value === ",") { } else if (state.tokens.next.value === ",") {
identifiers.push({ id: null, token: state.tokens.curr }); identifiers.push({ id: null, token: state.tokens.curr });
} else if (state.tokens.next.value === "(") {
advance("(");
nextInnerDE();
advance(")");
} else { } else {
ident = identifier(); ident = identifier();
if (ident) if (ident)
Expand Down
31 changes: 31 additions & 0 deletions tests/unit/fixtures/destparam.js
@@ -0,0 +1,31 @@
var foo;

// array
foo = ([a, b]) => { return a + b; };
foo = ([a, ((b))]) => { return a + b; };
foo = ([a, b], [c, d]) => { return a + b + c + d; };
foo = ([[[a, b], c], d]) => { return a + b + c + d; };

// array elision
foo = ([, a, b]) => { return a, b; };
foo = ([, a, , , b]) => { return a, b; };

// object
foo = ({a}) => { return a; };
foo = ({a, b}) => { return a + b; };
foo = ({a, b: y}, {c}) => { return a + y + c; };
foo = ({a: x, b: y}) => { return x + y; };
foo = ({a: (x), b: y}) => { return x + y; };

// array in object
foo = ({a: [x, y]}) => { return x + y; };
foo = ({a: [x, y], b: z}) => { return x + y + z; };
foo = ({a: [x, y], b: z, c}) => { return x + y + z + c; };
foo = ({a: ([x, y]), b: z, c}) => { return x + y + z + c; };

// object in array
foo = ([{a}]) => { return a; };
foo = ([{a, b}]) => { return a + b; };
foo = ([{a, b: y}]) => { return a + y; };
foo = ([{a: x, b: y}]) => { return x + y; };
foo = ([{a: (x), b: y}]) => { return x + y; };
116 changes: 116 additions & 0 deletions tests/unit/parser.js
Expand Up @@ -4127,3 +4127,119 @@ exports["jshint ignore:start/end should be detected using single line comments"]


test.done(); test.done();
}; };

exports["test destructuring function parameters as es5"] = function (test) {
var src = fs.readFileSync(__dirname + "/fixtures/destparam.js", "utf8");
TestRun(test)
.addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(4, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(5, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(6, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(7, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(10, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(10, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(11, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(11, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(14, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(14, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(15, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(15, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(16, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(16, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(16, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(17, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(17, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(18, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(18, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(21, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(22, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(22, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(22, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(23, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(23, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(23, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(24, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(24, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(24, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(27, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(27, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(27, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(28, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(28, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(28, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(29, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(29, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(29, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(30, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(30, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(30, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.test(src, {unused: true, undef: true});

test.done();
};

exports["test destructuring function parameters as legacy JS"] = function (test) {
var src = fs.readFileSync(__dirname + "/fixtures/destparam.js", "utf8");
TestRun(test)
.addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(4, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(5, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(6, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(7, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(10, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(10, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(11, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(11, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(14, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(14, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(15, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(15, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(16, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(16, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(16, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(17, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(17, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(18, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(18, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(21, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(22, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(22, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(22, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(23, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(23, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(23, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(24, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(24, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(24, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(27, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(27, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(27, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(28, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(28, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(28, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(29, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(29, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(29, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(30, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(30, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.addError(30, "'arrow function syntax (=>)' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
.test(src, {es3: true, unused: true, undef: true});

test.done();
};

0 comments on commit 9189c74

Please sign in to comment.