From 41df2833eff6e8362bb53b42b6647cb042a8148b Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Mon, 5 Feb 2018 20:22:00 +0900 Subject: [PATCH] Fix: support Rest/Spread Properties (fixes #9885) --- lib/rules/key-spacing.js | 5 +- lib/rules/no-self-assign.js | 4 +- lib/rules/no-unused-vars.js | 2 +- lib/rules/object-shorthand.js | 2 +- lib/rules/rest-spread-spacing.js | 6 + tests/lib/rules/comma-dangle.js | 5 + tests/lib/rules/key-spacing.js | 150 ++++++++++++-- tests/lib/rules/no-dupe-keys.js | 1 + tests/lib/rules/no-extra-parens.js | 25 ++- tests/lib/rules/no-self-assign.js | 2 + tests/lib/rules/no-undef.js | 14 ++ tests/lib/rules/no-unused-vars.js | 105 ++++++---- tests/lib/rules/no-useless-rename.js | 30 +++ tests/lib/rules/object-property-newline.js | 118 +++++++++++ tests/lib/rules/object-shorthand.js | 75 +++++++ tests/lib/rules/prefer-const.js | 12 ++ tests/lib/rules/quote-props.js | 5 +- tests/lib/rules/rest-spread-spacing.js | 224 ++++++++++++++++++++- tests/lib/rules/sort-keys.js | 10 + 19 files changed, 736 insertions(+), 59 deletions(-) diff --git a/lib/rules/key-spacing.js b/lib/rules/key-spacing.js index 1ae4990a594..b1208e19e97 100644 --- a/lib/rules/key-spacing.js +++ b/lib/rules/key-spacing.js @@ -360,9 +360,10 @@ module.exports = { */ function isKeyValueProperty(property) { return !( - (property.method || + property.method || property.shorthand || - property.kind !== "init" || property.type !== "Property") // Could be "ExperimentalSpreadProperty" or "SpreadProperty" + property.kind !== "init" || + property.type !== "Property" // Could be "ExperimentalSpreadProperty" or "SpreadElement" ); } diff --git a/lib/rules/no-self-assign.js b/lib/rules/no-self-assign.js index 30140420025..8091d7d2e58 100644 --- a/lib/rules/no-self-assign.js +++ b/lib/rules/no-self-assign.js @@ -121,7 +121,9 @@ function eachSelfAssignment(left, right, props, report) { let startJ = 0; for (let i = right.properties.length - 1; i >= 0; --i) { - if (right.properties[i].type === "ExperimentalSpreadProperty") { + const propType = right.properties[i].type; + + if (propType === "SpreadElement" || propType === "ExperimentalSpreadProperty") { startJ = i + 1; break; } diff --git a/lib/rules/no-unused-vars.js b/lib/rules/no-unused-vars.js index 1d0cef85628..6ba57349865 100644 --- a/lib/rules/no-unused-vars.js +++ b/lib/rules/no-unused-vars.js @@ -65,7 +65,7 @@ module.exports = { create(context) { const sourceCode = context.getSourceCode(); - const REST_PROPERTY_TYPE = /^(?:Experimental)?RestProperty$/; + const REST_PROPERTY_TYPE = /^(?:RestElement|(?:Experimental)?RestProperty)$/; const config = { vars: "all", diff --git a/lib/rules/object-shorthand.js b/lib/rules/object-shorthand.js index c6c0b104458..77be6209722 100644 --- a/lib/rules/object-shorthand.js +++ b/lib/rules/object-shorthand.js @@ -131,7 +131,7 @@ module.exports = { * */ function canHaveShorthand(property) { - return (property.kind !== "set" && property.kind !== "get" && property.type !== "SpreadProperty" && property.type !== "ExperimentalSpreadProperty"); + return (property.kind !== "set" && property.kind !== "get" && property.type !== "SpreadElement" && property.type !== "SpreadProperty" && property.type !== "ExperimentalSpreadProperty"); } /** diff --git a/lib/rules/rest-spread-spacing.js b/lib/rules/rest-spread-spacing.js index 1fbc2c4cc58..e87d881298b 100644 --- a/lib/rules/rest-spread-spacing.js +++ b/lib/rules/rest-spread-spacing.js @@ -47,9 +47,15 @@ module.exports = { switch (node.type) { case "SpreadElement": type = "spread"; + if (node.parent.type === "ObjectExpression") { + type += " property"; + } break; case "RestElement": type = "rest"; + if (node.parent.type === "ObjectPattern") { + type += " property"; + } break; case "ExperimentalSpreadProperty": type = "spread property"; diff --git a/tests/lib/rules/comma-dangle.js b/tests/lib/rules/comma-dangle.js index 29027e9496a..0a8403ebcfb 100644 --- a/tests/lib/rules/comma-dangle.js +++ b/tests/lib/rules/comma-dangle.js @@ -134,6 +134,11 @@ ruleTester.run("comma-dangle", rule, { options: ["always"], parserOptions: { ecmaVersion: 8, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var {foo, ...bar} = baz", + options: ["always"], + parserOptions: { ecmaVersion: 2018 } + }, // https://github.com/eslint/eslint/issues/3794 { diff --git a/tests/lib/rules/key-spacing.js b/tests/lib/rules/key-spacing.js index 5fa42b99908..183c91eb09f 100644 --- a/tests/lib/rules/key-spacing.js +++ b/tests/lib/rules/key-spacing.js @@ -383,6 +383,78 @@ ruleTester.run("key-spacing", rule, { align: "colon" }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + }, { + code: "({a : foo, ...x, b : bar})['a'];", + options: [{ + beforeColon: true, + afterColon: true + }], + parserOptions: { ecmaVersion: 2018 } + }, { + code: [ + "var obj = {", + " 'a' : (42 - 12),", + " ...x,", + " foobar : 'value',", + " [(expr)]: val", + "};" + ].join("\n"), + options: [{ + align: "colon" + }], + parserOptions: { ecmaVersion: 2018 } + }, { + code: [ + "callExpr(arg, {", + " key :val,", + " ...x,", + " ...y,", + " 'another' :false,", + " [compute] :'value'", + "});" + ].join("\n"), + options: [{ + align: "colon", + beforeColon: true, + afterColon: false + }], + parserOptions: { ecmaVersion: 2018 } + }, { + code: [ + "var obj = {", + " a: (42 - 12),", + " ...x,", + " 'foobar': 'value',", + " bat: function() {", + " return this.a;", + " },", + " baz: 42", + "};" + ].join("\n"), + options: [{ + align: "value" + }], + parserOptions: { ecmaVersion: 2018 } + }, { + code: [ + "({", + " ...x,", + " a : 0,", + " // same group", + " bcd: 0, /*", + " end of group */", + "", + " // different group", + " e: 0,", + " ...y,", + " /* group b */", + " f: 0", + "})" + ].join("\n"), + options: [{ + align: "colon" + }], + parserOptions: { ecmaVersion: 2018 } }, // https://github.com/eslint/eslint/issues/4792 @@ -524,7 +596,7 @@ ruleTester.run("key-spacing", rule, { beforeColon: true, afterColon: false }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "({", @@ -543,7 +615,7 @@ ruleTester.run("key-spacing", rule, { beforeColon: true, afterColon: false }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "({", @@ -561,7 +633,7 @@ ruleTester.run("key-spacing", rule, { } } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "({", @@ -577,7 +649,7 @@ ruleTester.run("key-spacing", rule, { afterColon: false } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } }, + parserOptions: { ecmaVersion: 6 }, errors: [] }, { code: [ @@ -595,7 +667,7 @@ ruleTester.run("key-spacing", rule, { mode: "minimum" } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "({", @@ -613,7 +685,7 @@ ruleTester.run("key-spacing", rule, { } } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "({", @@ -647,7 +719,7 @@ ruleTester.run("key-spacing", rule, { afterColon: true } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "({", @@ -678,7 +750,7 @@ ruleTester.run("key-spacing", rule, { afterColon: true } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "({", @@ -706,7 +778,7 @@ ruleTester.run("key-spacing", rule, { afterColon: false } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "var obj = {", @@ -731,7 +803,7 @@ ruleTester.run("key-spacing", rule, { } } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }, { code: [ "var obj = {", @@ -756,7 +828,7 @@ ruleTester.run("key-spacing", rule, { mode: "minimum" } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } + parserOptions: { ecmaVersion: 6 } }], invalid: [{ @@ -1323,6 +1395,43 @@ ruleTester.run("key-spacing", rule, { { message: "Missing space after key 'a'.", line: 3, column: 5, type: "Identifier" }, { message: "Extra space after key 'f'.", line: 12, column: 5, type: "Identifier" } ] + }, { + code: [ + "({", + " ...x,", + " a : 0,", + " // same group", + " bcd: 0, /*", + " end of group */", + "", + " // different group", + " e: 0,", + " ...y,", + " /* group b */", + " f : 0", + "})" + ].join("\n"), + output: [ + "({", + " ...x,", + " a : 0,", + " // same group", + " bcd: 0, /*", + " end of group */", + "", + " // different group", + " e: 0,", + " ...y,", + " /* group b */", + " f: 0", + "})" + ].join("\n"), + options: [{ align: "colon" }], + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { message: "Missing space after key 'a'.", line: 3, column: 5, type: "Identifier" }, + { message: "Extra space after key 'f'.", line: 12, column: 5, type: "Identifier" } + ] }, // https://github.com/eslint/eslint/issues/4792 @@ -1541,6 +1650,15 @@ ruleTester.run("key-spacing", rule, { { message: "Missing space before value for key 'a'.", line: 1, column: 6, type: "Identifier" }, { message: "Extra space after key 'c'.", line: 1, column: 20, type: "Identifier" } ] + }, { + code: "({ a:b, ...object, c : d })", + output: "({ a: b, ...object, c: d })", + options: [{ align: "colon" }], + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { message: "Missing space before value for key 'a'.", line: 1, column: 6, type: "Identifier" }, + { message: "Extra space after key 'c'.", line: 1, column: 20, type: "Identifier" } + ] }, // https://github.com/eslint/eslint/issues/5613 @@ -1567,7 +1685,7 @@ ruleTester.run("key-spacing", rule, { mode: "strict" } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } }, + parserOptions: { ecmaVersion: 6 }, errors: [ { message: "Missing space after key 'longName'.", line: 2, column: 5, type: "Identifier" }, { message: "Missing space before value for key 'longName'.", line: 2, column: 14, type: "Literal" }, @@ -1615,7 +1733,7 @@ ruleTester.run("key-spacing", rule, { mode: "strict" } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } }, + parserOptions: { ecmaVersion: 6 }, errors: [ { message: "Missing space before value for key 'func'.", line: 2, column: 10, type: "FunctionExpression" }, { message: "Missing space after key 'longName'.", line: 5, column: 5, type: "Identifier" }, @@ -1664,7 +1782,7 @@ ruleTester.run("key-spacing", rule, { } } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } }, + parserOptions: { ecmaVersion: 6 }, errors: [ { message: "Missing space before value for key 'func'.", line: 2, column: 10, type: "FunctionExpression" }, { message: "Missing space after key 'small'.", line: 6, column: 5, type: "Identifier" }, @@ -1706,7 +1824,7 @@ ruleTester.run("key-spacing", rule, { } } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } }, + parserOptions: { ecmaVersion: 6 }, errors: [ { message: "Extra space before value for key 'key2'.", line: 4, column: 14, type: "Literal" }, { message: "Extra space before value for key 'key3'.", line: 5, column: 14, type: "Literal" } @@ -1744,7 +1862,7 @@ ruleTester.run("key-spacing", rule, { on: "colon" } }], - parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } }, + parserOptions: { ecmaVersion: 6 }, errors: [ { message: "Extra space before value for key 'key2'.", line: 4, column: 14, type: "Literal" }, { message: "Extra space before value for key 'key3'.", line: 5, column: 14, type: "Literal" } diff --git a/tests/lib/rules/no-dupe-keys.js b/tests/lib/rules/no-dupe-keys.js index c8ca43b54d4..aeccfb4ced7 100644 --- a/tests/lib/rules/no-dupe-keys.js +++ b/tests/lib/rules/no-dupe-keys.js @@ -25,6 +25,7 @@ ruleTester.run("no-dupe-keys", rule, { "+{ get a() { }, set a(b) { } };", { code: "var x = { a: b, [a]: b };", parserOptions: { ecmaVersion: 6 } }, { code: "var x = { a: b, ...c }", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "var x = { a: b, ...c }", parserOptions: { ecmaVersion: 2018 } }, { code: "var x = { get a() {}, set a (value) {} };", parserOptions: { ecmaVersion: 6 } }, { code: "var x = { a: 1, b: { a: 2 } };", parserOptions: { ecmaVersion: 6 } }, { code: "var {a, a} = obj", parserOptions: { ecmaVersion: 6 } } diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index 3df00d516b4..93d669f88ee 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -46,9 +46,8 @@ function invalid(code, output, type, line, config) { const ruleTester = new RuleTester({ parserOptions: { - ecmaVersion: 8, + ecmaVersion: 2018, ecmaFeatures: { - experimentalObjectRestSpread: true, jsx: true } } @@ -409,8 +408,16 @@ ruleTester.run("no-extra-parens", rule, { "let a = [ ...b ]", "let a = { ...b }", + { + code: "let a = { ...b }", + parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } + }, "let a = [ ...(b, c) ]", "let a = { ...(b, c) }", + { + code: "let a = { ...(b, c) }", + parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } + }, "var [x = (1, foo)] = bar", "class A extends B {}", "const A = class extends B {}", @@ -954,6 +961,13 @@ ruleTester.run("no-extra-parens", rule, { "Identifier", 1 ), + invalid( + "let a = {...(b)}", + "let a = {...b}", + "Identifier", + 1, + { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } } + ), invalid( "let a = [...((b, c))]", "let a = [...(b, c)]", @@ -966,6 +980,13 @@ ruleTester.run("no-extra-parens", rule, { "SequenceExpression", 1 ), + invalid( + "let a = {...((b, c))}", + "let a = {...(b, c)}", + "SequenceExpression", + 1, + { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } } + ), invalid( "class A extends (B) {}", "class A extends B {}", diff --git a/tests/lib/rules/no-self-assign.js b/tests/lib/rules/no-self-assign.js index 76bd8b4c924..553ac460265 100644 --- a/tests/lib/rules/no-self-assign.js +++ b/tests/lib/rules/no-self-assign.js @@ -40,6 +40,7 @@ ruleTester.run("no-self-assign", rule, { { code: "({a} = {a() {}})", parserOptions: { ecmaVersion: 6 } }, { code: "({a} = {[a]: a})", parserOptions: { ecmaVersion: 6 } }, { code: "({a, ...b} = {a, ...b})", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "({a, ...b} = {a, ...b})", parserOptions: { ecmaVersion: 2018 } }, { code: "a.b = a.c", options: [{ props: true }] }, { code: "a.b = c.b", options: [{ props: true }] }, { code: "a.b = a[b]", options: [{ props: true }] }, @@ -68,6 +69,7 @@ ruleTester.run("no-self-assign", rule, { { code: "({a, b} = {c, a})", parserOptions: { ecmaVersion: 6 }, errors: ["'a' is assigned to itself."] }, { code: "({a: {b}, c: [d]} = {a: {b}, c: [d]})", parserOptions: { ecmaVersion: 6 }, errors: ["'b' is assigned to itself.", "'d' is assigned to itself."] }, { code: "({a, b} = {a, ...x, b})", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: ["'b' is assigned to itself."] }, + { code: "({a, b} = {a, ...x, b})", parserOptions: { ecmaVersion: 2018 }, errors: ["'b' is assigned to itself."] }, { code: "a.b = a.b", options: [{ props: true }], errors: ["'a.b' is assigned to itself."] }, { code: "a.b.c = a.b.c", options: [{ props: true }], errors: ["'a.b.c' is assigned to itself."] }, { code: "a[b] = a[b]", options: [{ props: true }], errors: ["'a[b]' is assigned to itself."] }, diff --git a/tests/lib/rules/no-undef.js b/tests/lib/rules/no-undef.js index 150e7ecbc61..bf7e775a6af 100644 --- a/tests/lib/rules/no-undef.js +++ b/tests/lib/rules/no-undef.js @@ -81,6 +81,13 @@ ruleTester.run("no-undef", rule, { } }, globals: { stuff: false, foo: false } + }, + { + code: "var {bacon, ...others} = stuff; foo(others)", + parserOptions: { + ecmaVersion: 2018 + }, + globals: { stuff: false, foo: false } } ], invalid: [ @@ -107,6 +114,13 @@ ruleTester.run("no-undef", rule, { } }, errors: [{ message: "'b' is not defined." }] + }, + { + code: "const c = 0; const a = {...b, c};", + parserOptions: { + ecmaVersion: 2018 + }, + errors: [{ message: "'b' is not defined." }] } ] }); diff --git a/tests/lib/rules/no-unused-vars.js b/tests/lib/rules/no-unused-vars.js index 9615c62dd8a..5fd39ede774 100644 --- a/tests/lib/rules/no-unused-vars.js +++ b/tests/lib/rules/no-unused-vars.js @@ -34,22 +34,6 @@ ruleTester.defineRule("use-every-a", context => { }; }); -/** - * Returns an extended test that includes es2017 parser options. - * @param {Object} test The test to extend - * @returns {Object} A parser-extended test case - */ -function includeRestPropertyParser(test) { - return Object.assign({ - parserOptions: { - ecmaVersion: 2017, - ecmaFeatures: { - experimentalObjectRestSpread: true - } - } - }, test); -} - /** * Returns an expected error for defined-but-not-used variables. * @param {string} varName The name of the variable @@ -196,10 +180,16 @@ ruleTester.run("no-unused-vars", rule, { }, // Using object rest for variable omission - includeRestPropertyParser({ + { + code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(coords);", + options: [{ ignoreRestSiblings: true }], + parserOptions: { ecmaVersion: 2015, ecmaFeatures: { experimentalObjectRestSpread: true } } + }, + { code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(coords);", - options: [{ ignoreRestSiblings: true }] - }), + options: [{ ignoreRestSiblings: true }], + parserOptions: { ecmaVersion: 2018 } + }, // https://github.com/eslint/eslint/issues/6348 "var a = 0, b; b = a = a + 1; foo(b);", @@ -282,10 +272,16 @@ ruleTester.run("no-unused-vars", rule, { }, // https://github.com/eslint/eslint/issues/8119 - includeRestPropertyParser({ + { code: "(({a, ...rest}) => rest)", - options: [{ args: "all", ignoreRestSiblings: true }] - }) + options: [{ args: "all", ignoreRestSiblings: true }], + parserOptions: { ecmaVersion: 2015, ecmaFeatures: { experimentalObjectRestSpread: true } } + }, + { + code: "(({a, ...rest}) => rest)", + options: [{ args: "all", ignoreRestSiblings: true }], + parserOptions: { ecmaVersion: 2018 } + } ], invalid: [ { code: "function foox() { return foox(); }", errors: [definedError("foox")] }, @@ -380,52 +376,93 @@ ruleTester.run("no-unused-vars", rule, { }, // Rest property sibling without ignoreRestSiblings - includeRestPropertyParser({ + { code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(coords);", + parserOptions: { ecmaVersion: 2015, ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [ { line: 2, column: 9, message: "'type' is assigned a value but never used." } ] - }), + }, + { + code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(coords);", + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { line: 2, column: 9, message: "'type' is assigned a value but never used." } + ] + }, // Unused rest property with ignoreRestSiblings - includeRestPropertyParser({ + { code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(type)", options: [{ ignoreRestSiblings: true }], + parserOptions: { ecmaVersion: 2015, ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [ { line: 2, column: 18, message: "'coords' is assigned a value but never used." } ] - }), + }, + { + code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(type)", + options: [{ ignoreRestSiblings: true }], + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { line: 2, column: 18, message: "'coords' is assigned a value but never used." } + ] + }, // Unused rest property without ignoreRestSiblings - includeRestPropertyParser({ + { code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(type)", + parserOptions: { ecmaVersion: 2015, ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [ { line: 2, column: 18, message: "'coords' is assigned a value but never used." } ] - }), + }, + { + code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(type)", + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { line: 2, column: 18, message: "'coords' is assigned a value but never used." } + ] + }, // Nested array destructuring with rest property - includeRestPropertyParser({ + { + code: "const data = { vars: ['x','y'], x: 1, y: 2 };\nconst { vars: [x], ...coords } = data;\n console.log(coords)", + parserOptions: { ecmaVersion: 2015, ecmaFeatures: { experimentalObjectRestSpread: true } }, + errors: [ + { line: 2, column: 16, message: "'x' is assigned a value but never used." } + ] + }, + { code: "const data = { vars: ['x','y'], x: 1, y: 2 };\nconst { vars: [x], ...coords } = data;\n console.log(coords)", + parserOptions: { ecmaVersion: 2018 }, errors: [ { line: 2, column: 16, message: "'x' is assigned a value but never used." } ] - }), + }, // Nested object destructuring with rest property - includeRestPropertyParser({ + { code: "const data = { defaults: { x: 0 }, x: 1, y: 2 };\nconst { defaults: { x }, ...coords } = data;\n console.log(coords)", + parserOptions: { ecmaVersion: 2015, ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [ { line: 2, column: 21, message: "'x' is assigned a value but never used." } ] - }), + }, // https://github.com/eslint/eslint/issues/8119 - includeRestPropertyParser({ + { code: "(({a, ...rest}) => {})", options: [{ args: "all", ignoreRestSiblings: true }], + parserOptions: { ecmaVersion: 2015, ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: ["'rest' is defined but never used."] - }), + }, + { + code: "(({a, ...rest}) => {})", + options: [{ args: "all", ignoreRestSiblings: true }], + parserOptions: { ecmaVersion: 2018 }, + errors: ["'rest' is defined but never used."] + }, // https://github.com/eslint/eslint/issues/3714 { diff --git a/tests/lib/rules/no-useless-rename.js b/tests/lib/rules/no-useless-rename.js index 5fad7768e93..325ab3cef77 100644 --- a/tests/lib/rules/no-useless-rename.js +++ b/tests/lib/rules/no-useless-rename.js @@ -52,14 +52,26 @@ ruleTester.run("no-useless-rename", rule, { code: "const {...stuff} = myObject;", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "const {...stuff} = myObject;", + parserOptions: { ecmaVersion: 2018 } + }, { code: "const {foo, ...stuff} = myObject;", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "const {foo, ...stuff} = myObject;", + parserOptions: { ecmaVersion: 2018 } + }, { code: "const {foo: bar, ...stuff} = myObject;", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "const {foo: bar, ...stuff} = myObject;", + parserOptions: { ecmaVersion: 2018 } + }, // { ignoreDestructuring: true } { @@ -228,18 +240,36 @@ ruleTester.run("no-useless-rename", rule, { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: ["Destructuring assignment foo unnecessarily renamed."] }, + { + code: "const {foo: foo, ...stuff} = myObject;", + output: "const {foo, ...stuff} = myObject;", + parserOptions: { ecmaVersion: 2018 }, + errors: ["Destructuring assignment foo unnecessarily renamed."] + }, { code: "const {foo: foo, bar: baz, ...stuff} = myObject;", output: "const {foo, bar: baz, ...stuff} = myObject;", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: ["Destructuring assignment foo unnecessarily renamed."] }, + { + code: "const {foo: foo, bar: baz, ...stuff} = myObject;", + output: "const {foo, bar: baz, ...stuff} = myObject;", + parserOptions: { ecmaVersion: 2018 }, + errors: ["Destructuring assignment foo unnecessarily renamed."] + }, { code: "const {foo: foo, bar: bar, ...stuff} = myObject;", output: "const {foo, bar, ...stuff} = myObject;", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: ["Destructuring assignment foo unnecessarily renamed.", "Destructuring assignment bar unnecessarily renamed."] }, + { + code: "const {foo: foo, bar: bar, ...stuff} = myObject;", + output: "const {foo, bar, ...stuff} = myObject;", + parserOptions: { ecmaVersion: 2018 }, + errors: ["Destructuring assignment foo unnecessarily renamed.", "Destructuring assignment bar unnecessarily renamed."] + }, { code: "import {foo as foo} from 'foo';", output: "import {foo} from 'foo';", diff --git a/tests/lib/rules/object-property-newline.js b/tests/lib/rules/object-property-newline.js index ed0e24db27a..6a6a2616c91 100644 --- a/tests/lib/rules/object-property-newline.js +++ b/tests/lib/rules/object-property-newline.js @@ -32,8 +32,11 @@ ruleTester.run("object-property-newline", rule, { "var obj = {};", { code: "var obj = {\n[bar]: 'baz',\nbaz\n};", parserOptions: { ecmaVersion: 6 } }, { code: "var obj = {\nk1: 'val1',\nk2: 'val2',\n...{}\n};", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "var obj = {\nk1: 'val1',\nk2: 'val2',\n...{}\n};", parserOptions: { ecmaVersion: 2018 } }, { code: "var obj = { k1: 'val1',\nk2: 'val2',\n...{} };", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "var obj = { k1: 'val1',\nk2: 'val2',\n...{} };", parserOptions: { ecmaVersion: 2018 } }, { code: "var obj = { ...{} };", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "var obj = { ...{} };", parserOptions: { ecmaVersion: 2018 } }, "foo({ k1: 'val1',\nk2: 'val2' });", "foo({\nk1: 'val1',\nk2: 'val2'\n});", { code: "foo({\na,\nb\n});", parserOptions: { ecmaVersion: 6 } }, @@ -41,8 +44,11 @@ ruleTester.run("object-property-newline", rule, { { code: "foo({\nbar() {},\nbaz\n});", parserOptions: { ecmaVersion: 6 } }, { code: "foo({\n[bar]: 'baz',\nbaz \n})", parserOptions: { ecmaVersion: 6 } }, { code: "foo({\nk1: 'val1',\nk2: 'val2',\n...{}\n});", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "foo({\nk1: 'val1',\nk2: 'val2',\n...{}\n});", parserOptions: { ecmaVersion: 2018 } }, { code: "foo({ k1: 'val1',\nk2: 'val2',\n...{} });", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "foo({ k1: 'val1',\nk2: 'val2',\n...{} });", parserOptions: { ecmaVersion: 2018 } }, { code: "foo({ ...{} });", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "foo({ ...{} });", parserOptions: { ecmaVersion: 2018 } }, // allowAllPropertiesOnSameLine: true { code: "var obj = { k1: 'val1', k2: 'val2', k3: 'val3' };", options: [{ allowAllPropertiesOnSameLine: true }] }, @@ -51,14 +57,18 @@ ruleTester.run("object-property-newline", rule, { { code: "var obj = {\nk1: 'val1'\n};", options: [{ allowAllPropertiesOnSameLine: true }] }, { code: "var obj = {};", options: [{ allowAllPropertiesOnSameLine: true }] }, { code: "var obj = { 'k1': 'val1', k2: 'val2', ...{} };", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "var obj = { 'k1': 'val1', k2: 'val2', ...{} };", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 2018 } }, { code: "var obj = {\n'k1': 'val1', k2: 'val2', ...{}\n};", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "var obj = {\n'k1': 'val1', k2: 'val2', ...{}\n};", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 2018 } }, { code: "foo({ k1: 'val1', k2: 'val2' });", options: [{ allowAllPropertiesOnSameLine: true }] }, { code: "foo({\nk1: 'val1', k2: 'val2'\n});", options: [{ allowAllPropertiesOnSameLine: true }] }, { code: "foo({ a, b });", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 6 } }, { code: "foo({ bar() {}, baz });", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 6 } }, { code: "foo({ [bar]: 'baz', baz })", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 6 } }, { code: "foo({ 'k1': 'val1', k2: 'val2', ...{} });", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "foo({ 'k1': 'val1', k2: 'val2', ...{} });", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 2018 } }, { code: "foo({\n'k1': 'val1', k2: 'val2', ...{}\n});", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "foo({\n'k1': 'val1', k2: 'val2', ...{}\n});", options: [{ allowAllPropertiesOnSameLine: true }], parserOptions: { ecmaVersion: 2018 } }, { code: "var obj = {k1: ['foo', 'bar'], k2: 'val1', k3: 'val2'};", options: [{ allowAllPropertiesOnSameLine: true }] }, { code: "var obj = {\nk1: ['foo', 'bar'], k2: 'val1', k3: 'val2'\n};", options: [{ allowAllPropertiesOnSameLine: true }] }, { code: "var obj = {\nk1: 'val1', k2: {e1: 'foo', e2: 'bar'}, k3: 'val2'\n};", options: [{ allowAllPropertiesOnSameLine: true }] }, @@ -216,6 +226,19 @@ ruleTester.run("object-property-newline", rule, { } ] }, + { + code: "var obj = { k1: 'val1', ...{} };", + output: "var obj = { k1: 'val1',\n...{} };", + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: "Object properties must go on a new line.", + type: "ObjectExpression", + line: 1, + column: 25 + } + ] + }, { code: "var obj = {\nk1: 'val1', ...{}\n};", output: "var obj = {\nk1: 'val1',\n...{}\n};", @@ -229,6 +252,19 @@ ruleTester.run("object-property-newline", rule, { } ] }, + { + code: "var obj = {\nk1: 'val1', ...{}\n};", + output: "var obj = {\nk1: 'val1',\n...{}\n};", + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: "Object properties must go on a new line.", + type: "ObjectExpression", + line: 2, + column: 13 + } + ] + }, { code: "foo({ k1: 'val1', k2: 'val2' });", output: "foo({ k1: 'val1',\nk2: 'val2' });", @@ -331,6 +367,19 @@ ruleTester.run("object-property-newline", rule, { } ] }, + { + code: "foo({ k1: 'val1', ...{} })", + output: "foo({ k1: 'val1',\n...{} })", + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: "Object properties must go on a new line.", + type: "ObjectExpression", + line: 1, + column: 19 + } + ] + }, { code: "foo({\nk1: 'val1', ...{}\n})", output: "foo({\nk1: 'val1',\n...{}\n})", @@ -344,6 +393,19 @@ ruleTester.run("object-property-newline", rule, { } ] }, + { + code: "foo({\nk1: 'val1', ...{}\n})", + output: "foo({\nk1: 'val1',\n...{}\n})", + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: "Object properties must go on a new line.", + type: "ObjectExpression", + line: 2, + column: 13 + } + ] + }, { code: "var obj = {\na: {\nb: 1,\nc: 2\n}, d: 2\n};", output: "var obj = {\na: {\nb: 1,\nc: 2\n},\nd: 2\n};", @@ -500,6 +562,20 @@ ruleTester.run("object-property-newline", rule, { } ] }, + { + code: "var obj = {\nk1: 'val1',\nk2: 'val2', ...{}\n};", + output: "var obj = {\nk1: 'val1',\nk2: 'val2',\n...{}\n};", + options: [{ allowAllPropertiesOnSameLine: true }], + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: "Object properties must go on a new line if they aren't all on the same line.", + type: "ObjectExpression", + line: 3, + column: 13 + } + ] + }, { code: "var obj = {\n...{},\nk1: 'val1', k2: 'val2'\n};", output: "var obj = {\n...{},\nk1: 'val1',\nk2: 'val2'\n};", @@ -514,6 +590,20 @@ ruleTester.run("object-property-newline", rule, { } ] }, + { + code: "var obj = {\n...{},\nk1: 'val1', k2: 'val2'\n};", + output: "var obj = {\n...{},\nk1: 'val1',\nk2: 'val2'\n};", + options: [{ allowAllPropertiesOnSameLine: true }], + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: "Object properties must go on a new line if they aren't all on the same line.", + type: "ObjectExpression", + line: 3, + column: 13 + } + ] + }, { code: "foo({ [\nk1]: 'val1', k2: 'val2' })", output: "foo({ [\nk1]: 'val1',\nk2: 'val2' })", @@ -542,6 +632,20 @@ ruleTester.run("object-property-newline", rule, { } ] }, + { + code: "foo({\nk1: 'val1',\nk2: 'val2', ...{}\n})", + output: "foo({\nk1: 'val1',\nk2: 'val2',\n...{}\n})", + options: [{ allowAllPropertiesOnSameLine: true }], + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: "Object properties must go on a new line if they aren't all on the same line.", + type: "ObjectExpression", + line: 3, + column: 13 + } + ] + }, { code: "foo({\n...{},\nk1: 'val1', k2: 'val2'\n})", output: "foo({\n...{},\nk1: 'val1',\nk2: 'val2'\n})", @@ -556,6 +660,20 @@ ruleTester.run("object-property-newline", rule, { } ] }, + { + code: "foo({\n...{},\nk1: 'val1', k2: 'val2'\n})", + output: "foo({\n...{},\nk1: 'val1',\nk2: 'val2'\n})", + options: [{ allowAllPropertiesOnSameLine: true }], + parserOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: "Object properties must go on a new line if they aren't all on the same line.", + type: "ObjectExpression", + line: 3, + column: 13 + } + ] + }, // allowMultiplePropertiesPerLine: true (deprecated) { diff --git a/tests/lib/rules/object-shorthand.js b/tests/lib/rules/object-shorthand.js index 0606d0ed812..90e06e067a3 100644 --- a/tests/lib/rules/object-shorthand.js +++ b/tests/lib/rules/object-shorthand.js @@ -176,6 +176,11 @@ ruleTester.run("object-shorthand", rule, { options: ["never"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var x = {foo: foo, bar: bar, ...baz}", + options: ["never"], + parserOptions: { ecmaVersion: 2018 } + }, // consistent { @@ -199,21 +204,41 @@ ruleTester.run("object-shorthand", rule, { options: ["consistent-as-needed"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var x = {...bar}", + options: ["consistent-as-needed"], + parserOptions: { ecmaVersion: 2018 } + }, { code: "var x = {foo, bar, ...baz}", options: ["consistent"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var x = {foo, bar, ...baz}", + options: ["consistent"], + parserOptions: { ecmaVersion: 2018 } + }, { code: "var x = {bar: baz, ...qux}", options: ["consistent"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var x = {bar: baz, ...qux}", + options: ["consistent"], + parserOptions: { ecmaVersion: 2018 } + }, { code: "var x = {...foo, bar: bar, baz: baz}", options: ["consistent"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var x = {...foo, bar: bar, baz: baz}", + options: ["consistent"], + parserOptions: { ecmaVersion: 2018 } + }, // consistent-as-needed { @@ -253,16 +278,31 @@ ruleTester.run("object-shorthand", rule, { options: ["consistent-as-needed"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var x = {bar, ...baz}", + options: ["consistent-as-needed"], + parserOptions: { ecmaVersion: 2018 } + }, { code: "var x = {bar: baz, ...qux}", options: ["consistent-as-needed"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var x = {bar: baz, ...qux}", + options: ["consistent-as-needed"], + parserOptions: { ecmaVersion: 2018 } + }, { code: "var x = {...foo, bar, baz}", options: ["consistent-as-needed"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "var x = {...foo, bar, baz}", + options: ["consistent-as-needed"], + parserOptions: { ecmaVersion: 2018 } + }, // avoidExplicitReturnArrows { @@ -690,6 +730,13 @@ ruleTester.run("object-shorthand", rule, { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [PROPERTY_ERROR] }, + { + code: "var x = {foo: foo, bar: baz, ...qux}", + output: "var x = {foo, bar: baz, ...qux}", + options: ["always"], + parserOptions: { ecmaVersion: 2018 }, + errors: [PROPERTY_ERROR] + }, { code: "var x = {foo, bar: baz, ...qux}", output: "var x = {foo: foo, bar: baz, ...qux}", @@ -697,6 +744,13 @@ ruleTester.run("object-shorthand", rule, { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [LONGFORM_PROPERTY_ERROR] }, + { + code: "var x = {foo, bar: baz, ...qux}", + output: "var x = {foo: foo, bar: baz, ...qux}", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [LONGFORM_PROPERTY_ERROR] + }, // avoidQuotes { @@ -750,6 +804,13 @@ ruleTester.run("object-shorthand", rule, { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [MIXED_SHORTHAND_ERROR] }, + { + code: "var x = {foo, bar: baz, ...qux}", + output: null, + options: ["consistent"], + parserOptions: { ecmaVersion: 2018 }, + errors: [MIXED_SHORTHAND_ERROR] + }, // consistent-as-needed { @@ -778,6 +839,13 @@ ruleTester.run("object-shorthand", rule, { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [ALL_SHORTHAND_ERROR] }, + { + code: "var x = {a: a, b: b, ...baz}", + output: null, + options: ["consistent-as-needed"], + parserOptions: { ecmaVersion: 2018 }, + errors: [ALL_SHORTHAND_ERROR] + }, { code: "var x = {foo, bar: bar, ...qux}", output: null, @@ -785,6 +853,13 @@ ruleTester.run("object-shorthand", rule, { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [MIXED_SHORTHAND_ERROR] }, + { + code: "var x = {foo, bar: bar, ...qux}", + output: null, + options: ["consistent-as-needed"], + parserOptions: { ecmaVersion: 2018 }, + errors: [MIXED_SHORTHAND_ERROR] + }, // avoidExplicitReturnArrows { diff --git a/tests/lib/rules/prefer-const.js b/tests/lib/rules/prefer-const.js index 31dceb45a62..a86335c0d60 100644 --- a/tests/lib/rules/prefer-const.js +++ b/tests/lib/rules/prefer-const.js @@ -95,6 +95,11 @@ ruleTester.run("prefer-const", rule, { options: [{ destructuring: "all" }], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { + code: "let { name, ...otherStuff } = obj; otherStuff = {};", + options: [{ destructuring: "all" }], + parserOptions: { ecmaVersion: 2018 } + }, { code: "let { name, ...otherStuff } = obj; otherStuff = {};", options: [{ destructuring: "all" }], @@ -311,6 +316,13 @@ ruleTester.run("prefer-const", rule, { parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } }, errors: [{ message: "'name' is never reassigned. Use 'const' instead.", type: "Identifier", column: 7 }] }, + { + code: "let { name, ...otherStuff } = obj; otherStuff = {};", + output: null, + options: [{ destructuring: "any" }], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ message: "'name' is never reassigned. Use 'const' instead.", type: "Identifier", column: 7 }] + }, { code: "let { name, ...otherStuff } = obj; otherStuff = {};", output: null, diff --git a/tests/lib/rules/quote-props.js b/tests/lib/rules/quote-props.js index 3ff23b7eeba..9c87da607cf 100644 --- a/tests/lib/rules/quote-props.js +++ b/tests/lib/rules/quote-props.js @@ -72,8 +72,11 @@ ruleTester.run("quote-props", rule, { { code: "({1: 1, x: 2})", options: ["consistent", { numbers: true }] }, { code: "({1: 1, x: 2})", options: ["consistent-as-needed", { numbers: true }] }, { code: "({ ...x })", options: ["as-needed"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "({ ...x })", options: ["as-needed"], parserOptions: { ecmaVersion: 2018 } }, { code: "({ ...x })", options: ["consistent"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, - { code: "({ ...x })", options: ["consistent-as-needed"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } } + { code: "({ ...x })", options: ["consistent"], parserOptions: { ecmaVersion: 2018 } }, + { code: "({ ...x })", options: ["consistent-as-needed"], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "({ ...x })", options: ["consistent-as-needed"], parserOptions: { ecmaVersion: 2018 } } ], invalid: [{ code: "({ a: 0 })", diff --git a/tests/lib/rules/rest-spread-spacing.js b/tests/lib/rules/rest-spread-spacing.js index d78499d3ddb..c7f28aa4a75 100644 --- a/tests/lib/rules/rest-spread-spacing.js +++ b/tests/lib/rules/rest-spread-spacing.js @@ -36,17 +36,29 @@ ruleTester.run("rest-spread-spacing", rule, { { code: "let [a, b, ...\tarr] = [1, 2, 3, 4, 5];", options: ["always"] }, { code: "let [a, b, ...\narr] = [1, 2, 3, 4, 5];", options: ["always"] }, { code: "let n = { x, y, ...z };", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let n = { x, y, ...z };", parserOptions: { ecmaVersion: 2018 } }, { code: "let n = { x, y, ...(z) };", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let n = { x, y, ...(z) };", parserOptions: { ecmaVersion: 2018 } }, { code: "let n = { x, y, ...( z ) };", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let n = { x, y, ...( z ) };", parserOptions: { ecmaVersion: 2018 } }, { code: "let n = { x, y, ...z };", options: ["never"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let n = { x, y, ...z };", options: ["never"], parserOptions: { ecmaVersion: 2018 } }, { code: "let n = { x, y, ... z };", options: ["always"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let n = { x, y, ... z };", options: ["always"], parserOptions: { ecmaVersion: 2018 } }, { code: "let n = { x, y, ...\tz };", options: ["always"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let n = { x, y, ...\tz };", options: ["always"], parserOptions: { ecmaVersion: 2018 } }, { code: "let n = { x, y, ...\nz };", options: ["always"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let n = { x, y, ...\nz };", options: ["always"], parserOptions: { ecmaVersion: 2018 } }, { code: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", parserOptions: { ecmaVersion: 2018 } }, { code: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", options: ["never"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", options: ["never"], parserOptions: { ecmaVersion: 2018 } }, { code: "let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 };", options: ["always"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 };", options: ["always"], parserOptions: { ecmaVersion: 2018 } }, { code: "let { x, y, ...\tz } = { x: 1, y: 2, a: 3, b: 4 };", options: ["always"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, - { code: "let { x, y, ...\nz } = { x: 1, y: 2, a: 3, b: 4 };", options: ["always"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } } + { code: "let { x, y, ...\tz } = { x: 1, y: 2, a: 3, b: 4 };", options: ["always"], parserOptions: { ecmaVersion: 2018 } }, + { code: "let { x, y, ...\nz } = { x: 1, y: 2, a: 3, b: 4 };", options: ["always"], parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "let { x, y, ...\nz } = { x: 1, y: 2, a: 3, b: 4 };", options: ["always"], parserOptions: { ecmaVersion: 2018 } } ], invalid: [ @@ -367,6 +379,17 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ... z };", + output: "let n = { x, y, ...z };", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Unexpected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ...\tz };", output: "let n = { x, y, ...z };", @@ -378,6 +401,17 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ...\tz };", + output: "let n = { x, y, ...z };", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Unexpected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ...\nz };", output: "let n = { x, y, ...z };", @@ -389,6 +423,17 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ...\nz };", + output: "let n = { x, y, ...z };", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Unexpected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ... z };", output: "let n = { x, y, ...z };", @@ -401,6 +446,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ... z };", + output: "let n = { x, y, ...z };", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Unexpected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ...\tz };", output: "let n = { x, y, ...z };", @@ -413,6 +470,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ...\tz };", + output: "let n = { x, y, ...z };", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Unexpected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ...\nz };", output: "let n = { x, y, ...z };", @@ -425,6 +494,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ...\nz };", + output: "let n = { x, y, ...z };", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Unexpected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ...z };", output: "let n = { x, y, ... z };", @@ -437,6 +518,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ...z };", + output: "let n = { x, y, ... z };", + options: ["always"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Expected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ... (z) };", output: "let n = { x, y, ...(z) };", @@ -449,6 +542,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ... (z) };", + output: "let n = { x, y, ...(z) };", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Unexpected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ... ( z ) };", output: "let n = { x, y, ...( z ) };", @@ -461,6 +566,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ... ( z ) };", + output: "let n = { x, y, ...( z ) };", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Unexpected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ...(z) };", output: "let n = { x, y, ... (z) };", @@ -473,6 +590,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ...(z) };", + output: "let n = { x, y, ... (z) };", + options: ["always"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Expected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let n = { x, y, ...( z ) };", output: "let n = { x, y, ... ( z ) };", @@ -485,6 +614,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalSpreadProperty" }] }, + { + code: "let n = { x, y, ...( z ) };", + output: "let n = { x, y, ... ( z ) };", + options: ["always"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 20, + message: "Expected whitespace after spread property operator.", + type: "SpreadElement" + }] + }, { code: "let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 };", output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", @@ -496,6 +637,17 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalRestProperty" }] }, + { + code: "let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 };", + output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 16, + message: "Unexpected whitespace after rest property operator.", + type: "RestElement" + }] + }, { code: "let { x, y, ...\tz } = { x: 1, y: 2, a: 3, b: 4 };", output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", @@ -507,6 +659,17 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalRestProperty" }] }, + { + code: "let { x, y, ...\tz } = { x: 1, y: 2, a: 3, b: 4 };", + output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 16, + message: "Unexpected whitespace after rest property operator.", + type: "RestElement" + }] + }, { code: "let { x, y, ...\nz } = { x: 1, y: 2, a: 3, b: 4 };", output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", @@ -518,6 +681,17 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalRestProperty" }] }, + { + code: "let { x, y, ...\nz } = { x: 1, y: 2, a: 3, b: 4 };", + output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 16, + message: "Unexpected whitespace after rest property operator.", + type: "RestElement" + }] + }, { code: "let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 };", output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", @@ -530,6 +704,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalRestProperty" }] }, + { + code: "let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 };", + output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 16, + message: "Unexpected whitespace after rest property operator.", + type: "RestElement" + }] + }, { code: "let { x, y, ...\tz } = { x: 1, y: 2, a: 3, b: 4 };", output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", @@ -542,6 +728,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalRestProperty" }] }, + { + code: "let { x, y, ...\tz } = { x: 1, y: 2, a: 3, b: 4 };", + output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 16, + message: "Unexpected whitespace after rest property operator.", + type: "RestElement" + }] + }, { code: "let { x, y, ...\nz } = { x: 1, y: 2, a: 3, b: 4 };", output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", @@ -554,6 +752,18 @@ ruleTester.run("rest-spread-spacing", rule, { type: "ExperimentalRestProperty" }] }, + { + code: "let { x, y, ...\nz } = { x: 1, y: 2, a: 3, b: 4 };", + output: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", + options: ["never"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 16, + message: "Unexpected whitespace after rest property operator.", + type: "RestElement" + }] + }, { code: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", output: "let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 };", @@ -565,6 +775,18 @@ ruleTester.run("rest-spread-spacing", rule, { message: "Expected whitespace after rest property operator.", type: "ExperimentalRestProperty" }] + }, + { + code: "let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };", + output: "let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 };", + options: ["always"], + parserOptions: { ecmaVersion: 2018 }, + errors: [{ + line: 1, + column: 16, + message: "Expected whitespace after rest property operator.", + type: "RestElement" + }] } ] }); diff --git a/tests/lib/rules/sort-keys.js b/tests/lib/rules/sort-keys.js index 82fbb42fbd4..2a94850a0f7 100644 --- a/tests/lib/rules/sort-keys.js +++ b/tests/lib/rules/sort-keys.js @@ -35,6 +35,7 @@ ruleTester.run("sort-keys", rule, { // ignore spread properties. { code: "var obj = {a:1, ...z, b:1}", options: [], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, + { code: "var obj = {a:1, ...z, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } }, // ignore destructuring patterns. { code: "let {a, b} = {}", options: [], parserOptions: { ecmaVersion: 6 } }, @@ -168,6 +169,15 @@ ruleTester.run("sort-keys", rule, { "Expected object keys to be in ascending order. 'a' should be before 'b'." ] }, + { + code: "var obj = {b:1, ...z, a:1}", + parserOptions: { + ecmaVersion: 2018 + }, + errors: [ + "Expected object keys to be in ascending order. 'a' should be before 'b'." + ] + }, // nested {