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

Update: Add never option for new-parens (refs #10034) #11379

Merged
merged 4 commits into from May 25, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
38 changes: 34 additions & 4 deletions docs/rules/new-parens.md
@@ -1,4 +1,4 @@
# require parentheses when invoking a constructor with no arguments (new-parens)
# Require parentheses when invoking a constructor with no arguments (new-parens)

JavaScript allows the omission of parentheses when invoking a function via the `new` keyword and the constructor has no arguments. However, some coders believe that omitting the parentheses is inconsistent with the rest of the language and thus makes code less clear.

Expand All @@ -8,9 +8,18 @@ var person = new Person;

## Rule Details

This rule requires parentheses when invoking a constructor with no arguments using the `new` keyword in order to increase code clarity.
This rule can enforce or disallow parentheses when invoking a constructor with no arguments using the `new` keyword.

Examples of **incorrect** code for this rule:
## Options

This rule takes one option.

- `"always"` enforces parenthesis after a new constructor with no arguments (default)
- `"never"` enforces no parenthesis after a new constructor with no arguments

### always

Examples of **incorrect** code for this rule with the `"always"` option:

```js
/*eslint new-parens: "error"*/
Expand All @@ -19,11 +28,32 @@ var person = new Person;
var person = new (Person);
```

Examples of **correct** code for this rule:
Examples of **correct** code for this rule with the `"always"` option:

```js
/*eslint new-parens: "error"*/

var person = new Person();
var person = new (Person)();
```

### never

Examples of **incorrect** code for this rule with the `"never"` option:

```js
/*eslint new-parens: ["error", "never"]*/

var person = new Person();
var person = new (Person)();
```

Examples of **correct** code for this rule with the `"never"` option:

```js
/*eslint new-parens: ["error", "never"]*/

var person = new Person;
var person = (new Person);
var person = new Person("Name");
```
50 changes: 41 additions & 9 deletions lib/rules/new-parens.js
Expand Up @@ -31,31 +31,63 @@ module.exports = {
},

fixable: "code",
schema: [],
schema: {
anyOf: [
{
type: "array",
items: [
{
enum: ["always", "never"]
}
],
minItems: 0,
maxItems: 1
}
]
},
messages: {
missing: "Missing '()' invoking a constructor."
missing: "Missing '()' invoking a constructor.",
using: "'()' included invoking a constructor with no arguments."
pfgithub marked this conversation as resolved.
Show resolved Hide resolved
}
},

create(context) {
const options = context.options;
const always = options[0] !== "never"; // Default is never
pfgithub marked this conversation as resolved.
Show resolved Hide resolved

const sourceCode = context.getSourceCode();

return {
NewExpression(node) {
if (node.arguments.length !== 0) {
return; // shortcut: if there are arguments, there have to be parens
return; // if there are arguments, there have to be parens
}

const lastToken = sourceCode.getLastToken(node);
const hasLastParen = lastToken && astUtils.isClosingParenToken(lastToken);
const hasParens = hasLastParen && astUtils.isOpeningParenToken(sourceCode.getTokenBefore(lastToken));

if (!hasParens) {
context.report({
node,
messageId: "missing",
fix: fixer => fixer.insertTextAfter(node, "()")
});
if (always) {
if (!hasParens) {
context.report({
node,
messageId: "missing",
fix: fixer => fixer.insertTextAfter(node, "()")
});
}
} else {
if (hasParens) {
context.report({
node,
messageId: "using",
fix: fixer => [
fixer.remove(sourceCode.getTokenBefore(lastToken)),
fixer.remove(lastToken),
fixer.insertTextBefore(node, "("),
fixer.insertTextAfter(node, ")")
]
});
}
}
}
};
Expand Down
62 changes: 61 additions & 1 deletion tests/lib/rules/new-parens.js
Expand Up @@ -17,6 +17,7 @@ const parser = require("../../fixtures/fixture-parser"),
// Tests
//------------------------------------------------------------------------------
const error = { messageId: "missing", type: "NewExpression" };
const neverError = { messageId: "using", type: "NewExpression" };

const ruleTester = new RuleTester();

Expand All @@ -29,7 +30,16 @@ ruleTester.run("new-parens", rule, {
"var a = (new Date());",
"var a = new foo.Bar();",
"var a = (new Foo()).bar;",
{ code: "new Storage<RootState>('state');", parser: parser("typescript-parsers/new-parens") }
{ code: "new Storage<RootState>('state');", parser: parser("typescript-parsers/new-parens") },

// Never
{ code: "var a = new Date;", options: ["never"] },
{ code: "var a = new Date(function() {});", options: ["never"] },
{ code: "var a = new (Date);", options: ["never"] },
{ code: "var a = new ((Date));", options: ["never"] },
{ code: "var a = (new Date);", options: ["never"] },
{ code: "var a = new foo.Bar;", options: ["never"] },
{ code: "var a = (new Foo).bar;", options: ["never"] }
],
invalid: [
{
Expand Down Expand Up @@ -73,6 +83,56 @@ ruleTester.run("new-parens", rule, {
code: "var a = (new Foo).bar;",
output: "var a = (new Foo()).bar;",
errors: [error]
},

// Never
{
code: "var a = new Date();",
output: "var a = (new Date);",
options: ["never"],
errors: [neverError]
},
{
code: "var a = new Date()",
output: "var a = (new Date)",
options: ["never"],
errors: [neverError]
},
{
code: "var a = new (Date)();",
output: "var a = (new (Date));",
options: ["never"],
errors: [neverError]
},
{
code: "var a = new (Date)()",
output: "var a = (new (Date))",
options: ["never"],
errors: [neverError]
},
{
code: "var a = (new Date())",
output: "var a = ((new Date))",
options: ["never"],
errors: [neverError]
},
{
code: "var a = (new Date())()",
output: "var a = ((new Date))()",
options: ["never"],
errors: [neverError]
},
{
code: "var a = new foo.Bar();",
output: "var a = (new foo.Bar);",
options: ["never"],
errors: [neverError]
},
{
code: "var a = (new Foo()).bar;",
output: "var a = ((new Foo)).bar;",
options: ["never"],
errors: [neverError]
}
]
});