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 12const astUtils = require("./utils/ast-utils"); 13 14//------------------------------------------------------------------------------ 15// Helpers 16//------------------------------------------------------------------------------ 17 18//------------------------------------------------------------------------------ 19// Rule Definition 20//------------------------------------------------------------------------------ 21 22module.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}; 100