]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
1 | /** |
2 | * @fileoverview Rule to flag when using constructor without parentheses | |
3 | * @author Ilya Volodin | |
4 | */ | |
5 | ||
6 | "use strict"; | |
7 | ||
8 | //------------------------------------------------------------------------------ | |
9 | // Requirements | |
10 | //------------------------------------------------------------------------------ | |
11 | ||
12 | const astUtils = require("./utils/ast-utils"); | |
13 | ||
14 | //------------------------------------------------------------------------------ | |
15 | // Helpers | |
16 | //------------------------------------------------------------------------------ | |
17 | ||
18 | //------------------------------------------------------------------------------ | |
19 | // Rule Definition | |
20 | //------------------------------------------------------------------------------ | |
21 | ||
22 | module.exports = { | |
23 | meta: { | |
24 | type: "layout", | |
25 | ||
26 | docs: { | |
27 | description: "enforce or disallow parentheses when invoking a constructor with no arguments", | |
28 | category: "Stylistic Issues", | |
29 | recommended: false, | |
30 | url: "https://eslint.org/docs/rules/new-parens" | |
31 | }, | |
32 | ||
33 | fixable: "code", | |
34 | schema: { | |
35 | anyOf: [ | |
36 | { | |
37 | type: "array", | |
38 | items: [ | |
39 | { | |
40 | enum: ["always", "never"] | |
41 | } | |
42 | ], | |
43 | minItems: 0, | |
44 | maxItems: 1 | |
45 | } | |
46 | ] | |
47 | }, | |
48 | messages: { | |
49 | missing: "Missing '()' invoking a constructor.", | |
50 | unnecessary: "Unnecessary '()' invoking a constructor with no arguments." | |
51 | } | |
52 | }, | |
53 | ||
54 | create(context) { | |
55 | const options = context.options; | |
56 | const always = options[0] !== "never"; // Default is always | |
57 | ||
58 | const sourceCode = context.getSourceCode(); | |
59 | ||
60 | return { | |
61 | NewExpression(node) { | |
62 | if (node.arguments.length !== 0) { | |
63 | return; // if there are arguments, there have to be parens | |
64 | } | |
65 | ||
66 | const lastToken = sourceCode.getLastToken(node); | |
67 | const hasLastParen = lastToken && astUtils.isClosingParenToken(lastToken); | |
68 | ||
69 | // `hasParens` is true only if the new expression ends with its own parens, e.g., new new foo() does not end with its own parens | |
70 | const hasParens = hasLastParen && | |
71 | astUtils.isOpeningParenToken(sourceCode.getTokenBefore(lastToken)) && | |
72 | node.callee.range[1] < node.range[1]; | |
73 | ||
74 | if (always) { | |
75 | if (!hasParens) { | |
76 | context.report({ | |
77 | node, | |
78 | messageId: "missing", | |
79 | fix: fixer => fixer.insertTextAfter(node, "()") | |
80 | }); | |
81 | } | |
82 | } else { | |
83 | if (hasParens) { | |
84 | context.report({ | |
85 | node, | |
86 | messageId: "unnecessary", | |
87 | fix: fixer => [ | |
88 | fixer.remove(sourceCode.getTokenBefore(lastToken)), | |
89 | fixer.remove(lastToken), | |
90 | fixer.insertTextBefore(node, "("), | |
91 | fixer.insertTextAfter(node, ")") | |
92 | ] | |
93 | }); | |
94 | } | |
95 | } | |
96 | } | |
97 | }; | |
98 | } | |
99 | }; |