From 7502eedcf1835272d2b6893e7628a40ed8514404 Mon Sep 17 00:00:00 2001 From: Gyandeep Singh Date: Thu, 8 Sep 2016 03:49:17 -0500 Subject: [PATCH] Update: auto-fix for `comma-style` (fixes #6941) (#6957) --- docs/rules/comma-style.md | 2 + lib/rules/comma-style.js | 77 +++++++++++++++++++++++++++++----- tests/lib/rules/comma-style.js | 52 +++++++++++++++++++++++ 3 files changed, 121 insertions(+), 10 deletions(-) diff --git a/docs/rules/comma-style.md b/docs/rules/comma-style.md index 16bf03900b5..37ffabdbea3 100644 --- a/docs/rules/comma-style.md +++ b/docs/rules/comma-style.md @@ -1,5 +1,7 @@ # Comma style (comma-style) +(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule. + The Comma Style rule enforces styles for comma-separated lists. There are two comma styles primarily used in JavaScript: * The standard style, in which commas are placed at the end of the current line diff --git a/lib/rules/comma-style.js b/lib/rules/comma-style.js index 1ce226b39f8..f707ce80557 100644 --- a/lib/rules/comma-style.js +++ b/lib/rules/comma-style.js @@ -18,7 +18,7 @@ module.exports = { category: "Stylistic Issues", recommended: false }, - + fixable: "code", schema: [ { enum: ["first", "last"] @@ -61,6 +61,49 @@ module.exports = { return !!token && (token.type === "Punctuator") && (token.value === ","); } + /** + * Modified text based on the style + * @param {string} styleType Style type + * @param {string} text Source code text + * @returns {string} modified text + * @private + */ + function getReplacedText(styleType, text) { + switch (styleType) { + case "between": + return `,${text.replace("\n", "")}`; + + case "first": + return `${text},`; + + case "last": + return `,${text}`; + + default: + return ""; + } + } + + /** + * Determines the fixer function for a given style. + * @param {string} styleType comma style + * @param {ASTNode} previousItemToken The token to check. + * @param {ASTNode} commaToken The token to check. + * @param {ASTNode} currentItemToken The token to check. + * @returns {Function} Fixer function + * @private + */ + function getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken) { + const text = + sourceCode.text.slice(previousItemToken.range[1], commaToken.range[0]) + + sourceCode.text.slice(commaToken.range[1], currentItemToken.range[0]); + const range = [previousItemToken.range[1], currentItemToken.range[0]]; + + return function(fixer) { + return fixer.replaceTextRange(range, getReplacedText(styleType, text)); + }; + } + /** * Validates the spacing around single items in lists. * @param {Token} previousItemToken The last token from the previous item. @@ -82,21 +125,35 @@ module.exports = { !astUtils.isTokenOnSameLine(previousItemToken, commaToken)) { // lone comma - context.report(reportItem, { - line: commaToken.loc.end.line, - column: commaToken.loc.start.column - }, "Bad line breaking before and after ','."); + context.report({ + node: reportItem, + loc: { + line: commaToken.loc.end.line, + column: commaToken.loc.start.column + }, + message: "Bad line breaking before and after ','.", + fix: getFixerFunction("between", previousItemToken, commaToken, currentItemToken) + }); } else if (style === "first" && !astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { - context.report(reportItem, "',' should be placed first."); + context.report({ + node: reportItem, + message: "',' should be placed first.", + fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken) + }); } else if (style === "last" && astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { - context.report(reportItem, { - line: commaToken.loc.end.line, - column: commaToken.loc.end.column - }, "',' should be placed last."); + context.report({ + node: reportItem, + loc: { + line: commaToken.loc.end.line, + column: commaToken.loc.end.column + }, + message: "',' should be placed last.", + fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken) + }); } } diff --git a/tests/lib/rules/comma-style.js b/tests/lib/rules/comma-style.js index 9c5378e249f..6ed9c6a9bc8 100644 --- a/tests/lib/rules/comma-style.js +++ b/tests/lib/rules/comma-style.js @@ -86,8 +86,41 @@ ruleTester.run("comma-style", rule, { ], invalid: [ + { + code: "var foo = { a: 1. //comment \n, b: 2\n}", + output: "var foo = { a: 1., //comment \n b: 2\n}", + errors: [{ + message: LAST_MSG, + type: "Property" + }] + }, + { + code: "var foo = { a: 1. //comment \n //comment1 \n //comment2 \n, b: 2\n}", + output: "var foo = { a: 1., //comment \n //comment1 \n //comment2 \n b: 2\n}", + errors: [{ + message: LAST_MSG, + type: "Property" + }] + }, { code: "var foo = 1\n,\nbar = 2;", + output: "var foo = 1,\nbar = 2;", + errors: [{ + message: BAD_LN_BRK_MSG, + type: "VariableDeclarator" + }] + }, + { + code: "var foo = 1 //comment\n,\nbar = 2;", + output: "var foo = 1, //comment\nbar = 2;", + errors: [{ + message: BAD_LN_BRK_MSG, + type: "VariableDeclarator" + }] + }, + { + code: "var foo = 1 //comment\n, // comment 2\nbar = 2;", + output: "var foo = 1, //comment // comment 2\nbar = 2;", errors: [{ message: BAD_LN_BRK_MSG, type: "VariableDeclarator" @@ -95,6 +128,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var foo = 1\n,bar = 2;", + output: "var foo = 1,\nbar = 2;", errors: [{ message: LAST_MSG, type: "VariableDeclarator" @@ -102,6 +136,7 @@ ruleTester.run("comma-style", rule, { }, { code: "f([1,2\n,3]);", + output: "f([1,2,\n3]);", errors: [{ message: LAST_MSG, type: "Literal" @@ -109,6 +144,7 @@ ruleTester.run("comma-style", rule, { }, { code: "f([1,2\n,]);", + output: "f([1,2,\n]);", errors: [{ message: LAST_MSG, type: "Punctuator" @@ -116,6 +152,7 @@ ruleTester.run("comma-style", rule, { }, { code: "f([,2\n,3]);", + output: "f([,2,\n3]);", errors: [{ message: LAST_MSG, type: "Literal" @@ -123,6 +160,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var foo = ['apples'\n, 'oranges'];", + output: "var foo = ['apples',\n 'oranges'];", errors: [{ message: LAST_MSG, type: "Literal" @@ -130,6 +168,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var foo = 1,\nbar = 2;", + output: "var foo = 1\n,bar = 2;", options: ["first"], errors: [{ message: FIRST_MSG, @@ -138,6 +177,7 @@ ruleTester.run("comma-style", rule, { }, { code: "f([1,\n2,3]);", + output: "f([1\n,2,3]);", options: ["first"], errors: [{ message: FIRST_MSG, @@ -146,6 +186,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var foo = ['apples', \n 'oranges'];", + output: "var foo = ['apples' \n ,'oranges'];", options: ["first"], errors: [{ message: FIRST_MSG, @@ -154,6 +195,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var foo = {'a': 1, \n 'b': 2\n ,'c': 3};", + output: "var foo = {'a': 1 \n ,'b': 2\n ,'c': 3};", options: ["first"], errors: [{ message: FIRST_MSG, @@ -162,6 +204,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var foo = {'a': 1, \n 'b': 2\n ,'c': 3};", + output: "var foo = {'a': 1 \n ,'b': 2\n ,'c': 3};", options: ["first"], errors: [{ message: FIRST_MSG, @@ -170,6 +213,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var a = 'a',\no = 'o',\narr = [1,\n2];", + output: "var a = 'a',\no = 'o',\narr = [1\n,2];", options: ["first", {exceptions: {VariableDeclaration: true}}], errors: [{ message: FIRST_MSG, @@ -178,6 +222,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var a = 'a',\nobj = {a: 'a',\nb: 'b'};", + output: "var a = 'a',\nobj = {a: 'a'\n,b: 'b'};", options: ["first", {exceptions: {VariableDeclaration: true}}], errors: [{ message: FIRST_MSG, @@ -186,6 +231,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var a = 'a',\nobj = {a: 'a',\nb: 'b'};", + output: "var a = 'a'\n,obj = {a: 'a',\nb: 'b'};", options: ["first", {exceptions: {ObjectExpression: true}}], errors: [{ message: FIRST_MSG, @@ -194,6 +240,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var a = 'a',\narr = [1,\n2];", + output: "var a = 'a'\n,arr = [1,\n2];", options: ["first", {exceptions: {ArrayExpression: true}}], errors: [{ message: FIRST_MSG, @@ -202,6 +249,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var ar =[1,\n{a: 'a',\nb: 'b'}];", + output: "var ar =[1,\n{a: 'a'\n,b: 'b'}];", options: ["first", {exceptions: {ArrayExpression: true}}], errors: [{ message: FIRST_MSG, @@ -210,6 +258,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var ar =[1,\n{a: 'a',\nb: 'b'}];", + output: "var ar =[1\n,{a: 'a',\nb: 'b'}];", options: ["first", {exceptions: {ObjectExpression: true}}], errors: [{ message: FIRST_MSG, @@ -218,6 +267,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var ar ={fst:1,\nsnd: [1,\n2]};", + output: "var ar ={fst:1,\nsnd: [1\n,2]};", options: ["first", {exceptions: {ObjectExpression: true}}], errors: [{ message: FIRST_MSG, @@ -226,6 +276,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var ar ={fst:1,\nsnd: [1,\n2]};", + output: "var ar ={fst:1\n,snd: [1,\n2]};", options: ["first", {exceptions: {ArrayExpression: true}}], errors: [{ message: FIRST_MSG, @@ -234,6 +285,7 @@ ruleTester.run("comma-style", rule, { }, { code: "var foo = [\n(bar\n)\n,\nbaz\n];", + output: "var foo = [\n(bar\n),\nbaz\n];", errors: [{ message: BAD_LN_BRK_MSG, type: "Identifier"