Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: Add fixer for object-shorthand (fixes #6412) #6418

Merged
merged 1 commit into from Jun 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
80 changes: 75 additions & 5 deletions lib/rules/object-shorthand.js
Expand Up @@ -23,6 +23,8 @@ module.exports = {
recommended: false
},

fixable: "code",

schema: {
anyOf: [
{
Expand Down Expand Up @@ -132,12 +134,36 @@ module.exports = {
// if we're "never" and concise we should warn now
if (APPLY_NEVER && isConciseProperty) {
type = node.method ? "method" : "property";
context.report(node, "Expected longform " + type + " syntax.");
context.report({
node: node,
message: "Expected longform " + type + " syntax.",
fix: function(fixer) {
if (node.method) {
if (node.value.generator) {
return fixer.replaceTextRange([node.range[0], node.key.range[1]], node.key.name + ": function*");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting for other reviewers that the star spacing might be wrong here-- this will be fixed by another pass in auto-fix. This would also be another example of something that could go into a shared repository settings config. (@NickHeiner you can ignore this)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I was thinking about things like that! I'm glad to hear that it's not an issue for this PR.

}

return fixer.insertTextAfter(node.key, ": function");
}

return fixer.insertTextAfter(node.key, ": " + node.key.name);
}
});
}

// {'xyz'() {}} should be written as {'xyz': function() {}}
if (AVOID_QUOTES && isStringLiteral(node.key) && isConciseProperty) {
context.report(node, "Expected longform method syntax for string literal keys.");
context.report({
node: node,
message: "Expected longform method syntax for string literal keys.",
fix: function(fixer) {
if (node.computed) {
return fixer.insertTextAfterRange([node.key.range[0], node.key.range[1] + 1], ": function");
}

return fixer.insertTextAfter(node.key, ": function");
}
});
}

// at this point if we're concise or if we're "never" we can leave
Expand All @@ -160,16 +186,60 @@ module.exports = {
return;
}

// {[x]: function(){}} should be written as {[x]() {}}
if (node.computed) {
context.report({
node: node,
message: "Expected method shorthand.",
fix: function(fixer) {
if (node.value.generator) {
return fixer.replaceTextRange(
[node.key.range[0], node.value.range[0] + "function*".length],
"*[" + node.key.name + "]"
);
}

return fixer.removeRange([node.key.range[1] + 1, node.value.range[0] + "function".length]);
}
});
return;
}

// {x: function(){}} should be written as {x() {}}
context.report(node, "Expected method shorthand.");
context.report({
node: node,
message: "Expected method shorthand.",
fix: function(fixer) {
if (node.value.generator) {
return fixer.replaceTextRange(
[node.key.range[0], node.value.range[0] + "function*".length],
"*" + node.key.name
);
}

return fixer.removeRange([node.key.range[1], node.value.range[0] + "function".length]);
}
});
} else if (node.value.type === "Identifier" && node.key.name === node.value.name && APPLY_TO_PROPS) {

// {x: x} should be written as {x}
context.report(node, "Expected property shorthand.");
context.report({
node: node,
message: "Expected property shorthand.",
fix: function(fixer) {
return fixer.replaceText(node, node.value.name);
}
});
} else if (node.value.type === "Identifier" && node.key.type === "Literal" && node.key.value === node.value.name && APPLY_TO_PROPS) {

// {"x": x} should be written as {x}
context.report(node, "Expected property shorthand.");
context.report({
node: node,
message: "Expected property shorthand.",
fix: function(fixer) {
return fixer.replaceText(node, node.value.name);
}
});
}
}
};
Expand Down
73 changes: 40 additions & 33 deletions tests/lib/rules/object-shorthand.js
Expand Up @@ -96,40 +96,47 @@ ruleTester.run("object-shorthand", rule, {
{ code: "let {a, b} = o;", parserOptions: { ecmaVersion: 6 }, options: ["never"] }
],
invalid: [
{ code: "var x = {x: x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {'x': x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {y: y, x: x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }, { message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {y: z, x: x, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {y: function() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {y: function*() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {x: y, y: z, a: a}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {ConstructorFunction: function(){}, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {x: y, y: z, a: function(){}, b() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {x: x, y: function() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }, { message: "Expected method shorthand.", type: "Property" }]},
{ code: "doSomething({x: x})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "doSomething({'x': x})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "doSomething({a: 'a', 'x': x})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "doSomething({y: function() {}})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "doSomething({[y]: function() {}})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "doSomething({['y']: function() {}})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {x: x}", output: "var x = {x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {'x': x}", output: "var x = {x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {y: y, x: x}", output: "var x = {y, x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }, { message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {y: z, x: x, a: b}", output: "var x = {y: z, x, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {y: z,\n x: x,\n a: b\n // comment \n}", output: "var x = {y: z,\n x,\n a: b\n // comment \n}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {y: z,\n a: b,\n // comment \nf: function() {}}", output: "var x = {y: z,\n a: b,\n // comment \nf() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {a: b,\n/* comment */\ny: y\n }", output: "var x = {a: b,\n/* comment */\ny\n }", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {\n a: b,\n /* comment */\n y: y\n}", output: "var x = {\n a: b,\n /* comment */\n y\n}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {\n f: function() {\n /* comment */\n a(b);\n }\n }", output: "var x = {\n f() {\n /* comment */\n a(b);\n }\n }", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {\n [f]: function() {\n /* comment */\n a(b);\n }\n }", output: "var x = {\n [f]() {\n /* comment */\n a(b);\n }\n }", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {\n f: function*() {\n /* comment */\n a(b);\n }\n }", output: "var x = {\n *f() {\n /* comment */\n a(b);\n }\n }", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {y: function() {}}", output: "var x = {y() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {y: function*() {}}", output: "var x = {*y() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {x: y, y: z, a: a}", output: "var x = {x: y, y: z, a}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "var x = {ConstructorFunction: function(){}, a: b}", output: "var x = {ConstructorFunction(){}, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {x: y, y: z, a: function(){}, b() {}}", output: "var x = {x: y, y: z, a(){}, b() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "var x = {x: x, y: function() {}}", output: "var x = {x, y() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }, { message: "Expected method shorthand.", type: "Property" }]},
{ code: "doSomething({x: x})", output: "doSomething({x})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "doSomething({'x': x})", output: "doSomething({x})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "doSomething({a: 'a', 'x': x})", output: "doSomething({a: 'a', x})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }] },
{ code: "doSomething({y: function() {}})", output: "doSomething({y() {}})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "doSomething({[y]: function() {}})", output: "doSomething({[y]() {}})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },
{ code: "doSomething({['y']: function() {}})", output: "doSomething({['y']() {}})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }] },

// options
{ code: "var x = {y: function() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }], options: ["methods"] },
{ code: "var x = {x, y() {}, z: function() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }], options: ["methods"] },
{ code: "var x = {ConstructorFunction: function(){}, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }], options: ["methods"] },
{ code: "var x = {[y]: function() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }], options: ["methods"] },
{ code: "var x = {x: x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }], options: ["properties"] },
{ code: "var x = {a, b, c(){}, x: x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }], options: ["properties"] },
{ code: "var x = {y() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },
{ code: "var x = {*y() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },
{ code: "var x = {y}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform property syntax.", type: "Property" }], options: ["never"]},
{ code: "var x = {y, a: b, *x(){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform property syntax.", type: "Property" }, { message: "Expected longform method syntax.", type: "Property" }], options: ["never"]},
{ code: "var x = {y: {x}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform property syntax.", type: "Property" }], options: ["never"]},
{ code: "var x = {ConstructorFunction(){}, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },
{ code: "var x = {notConstructorFunction(){}, b: c}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },

// avoidQuotes
{ code: "var x = {'a'(){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax for string literal keys.", type: "Property" }], options: ["always", {avoidQuotes: true}] },
{ code: "var x = {['a'](){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax for string literal keys.", type: "Property" }], options: ["methods", {avoidQuotes: true}] }
{ code: "var x = {y: function() {}}", output: "var x = {y() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }], options: ["methods"] },
{ code: "var x = {x, y() {}, z: function() {}}", output: "var x = {x, y() {}, z() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }], options: ["methods"] },
{ code: "var x = {ConstructorFunction: function(){}, a: b}", output: "var x = {ConstructorFunction(){}, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }], options: ["methods"] },
{ code: "var x = {[y]: function() {}}", output: "var x = {[y]() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected method shorthand.", type: "Property" }], options: ["methods"] },
{ code: "var x = {x: x}", output: "var x = {x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }], options: ["properties"] },
{ code: "var x = {a, b, c(){}, x: x}", output: "var x = {a, b, c(){}, x}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected property shorthand.", type: "Property" }], options: ["properties"] },
{ code: "var x = {y() {}}", output: "var x = {y: function() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },
{ code: "var x = {*y() {}}", output: "var x = {y: function*() {}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },
{ code: "var x = {y}", output: "var x = {y: y}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform property syntax.", type: "Property" }], options: ["never"]},
{ code: "var x = {y, a: b, *x(){}}", output: "var x = {y: y, a: b, x: function*(){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform property syntax.", type: "Property" }, { message: "Expected longform method syntax.", type: "Property" }], options: ["never"]},
{ code: "var x = {y: {x}}", output: "var x = {y: {x: x}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform property syntax.", type: "Property" }], options: ["never"]},
{ code: "var x = {ConstructorFunction(){}, a: b}", output: "var x = {ConstructorFunction: function(){}, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },
{ code: "var x = {notConstructorFunction(){}, b: c}", output: "var x = {notConstructorFunction: function(){}, b: c}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },

// // avoidQuotes
{ code: "var x = {'a'(){}}", output: "var x = {'a': function(){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax for string literal keys.", type: "Property" }], options: ["always", {avoidQuotes: true}] },
{ code: "var x = {['a'](){}}", output: "var x = {['a']: function(){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax for string literal keys.", type: "Property" }], options: ["methods", {avoidQuotes: true}] }
]
});