diff --git a/packages/eslint-plugin/src/rules/no-array-constructor.ts b/packages/eslint-plugin/src/rules/no-array-constructor.ts index a315789334e4..93b4256066a4 100644 --- a/packages/eslint-plugin/src/rules/no-array-constructor.ts +++ b/packages/eslint-plugin/src/rules/no-array-constructor.ts @@ -1,8 +1,12 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; +import { + isOpeningParenToken, + isClosingParenToken, +} from '@typescript-eslint/utils/ast-utils'; -import { createRule, isOptionalCallExpression } from '../util'; +import { createRule } from '../util'; export default createRule({ name: 'no-array-constructor', @@ -21,6 +25,29 @@ export default createRule({ }, defaultOptions: [], create(context) { + const sourceCode = context.sourceCode; + + function getArgumentsText( + node: TSESTree.CallExpression | TSESTree.NewExpression, + ) { + const lastToken = sourceCode.getLastToken(node); + + if (lastToken == null || !isClosingParenToken(lastToken)) { + return ''; + } + + let firstToken: TSESTree.Expression | TSESTree.Token | null = node.callee; + + do { + firstToken = sourceCode.getTokenAfter(firstToken); + if (!firstToken || firstToken === lastToken) { + return ''; + } + } while (!isOpeningParenToken(firstToken)); + + return sourceCode.text.slice(firstToken.range[1], lastToken.range[0]); + } + /** * Disallow construction of dense arrays using the Array constructor * @param node node to evaluate @@ -32,23 +59,15 @@ export default createRule({ node.arguments.length !== 1 && node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === 'Array' && - !node.typeArguments && - !isOptionalCallExpression(node) + !node.typeArguments ) { context.report({ node, messageId: 'useLiteral', fix(fixer) { - if (node.arguments.length === 0) { - return fixer.replaceText(node, '[]'); - } - const fullText = context.sourceCode.getText(node); - const preambleLength = node.callee.range[1] - node.range[0]; - - return fixer.replaceText( - node, - `[${fullText.slice(preambleLength + 1, -1)}]`, - ); + const argsText = getArgumentsText(node); + + return fixer.replaceText(node, `[${argsText}]`); }, }); } diff --git a/packages/eslint-plugin/tests/rules/no-array-constructor.test.ts b/packages/eslint-plugin/tests/rules/no-array-constructor.test.ts index 4ce184ce984b..bbba24e7b75c 100644 --- a/packages/eslint-plugin/tests/rules/no-array-constructor.test.ts +++ b/packages/eslint-plugin/tests/rules/no-array-constructor.test.ts @@ -33,8 +33,6 @@ ruleTester.run('no-array-constructor', rule, { 'Array.foo?.();', 'Array?.(1, 2, 3);', 'Array?.();', - 'Array?.(0, 1, 2);', - 'Array?.(x, y);', ], invalid: [ @@ -58,6 +56,26 @@ ruleTester.run('no-array-constructor', rule, { ], output: '[];', }, + { + code: 'Array?.();', + errors: [ + { + messageId, + type: AST_NODE_TYPES.CallExpression, + }, + ], + output: '[];', + }, + { + code: '/* a */ /* b */ Array /* c */ /* d */ /* e */ /* f */?.(); /* g */ /* h */', + errors: [ + { + messageId, + type: AST_NODE_TYPES.CallExpression, + }, + ], + output: '/* a */ /* b */ []; /* g */ /* h */', + }, { code: 'new Array(x, y);', errors: [ @@ -78,6 +96,26 @@ ruleTester.run('no-array-constructor', rule, { ], output: '[x, y];', }, + { + code: 'Array?.(x, y);', + errors: [ + { + messageId, + type: AST_NODE_TYPES.CallExpression, + }, + ], + output: '[x, y];', + }, + { + code: '/* a */ /* b */ Array /* c */ /* d */ /* e */ /* f */?.(x, y); /* g */ /* h */', + errors: [ + { + messageId, + type: AST_NODE_TYPES.CallExpression, + }, + ], + output: '/* a */ /* b */ [x, y]; /* g */ /* h */', + }, { code: 'new Array(0, 1, 2);', errors: [ @@ -98,6 +136,38 @@ ruleTester.run('no-array-constructor', rule, { ], output: '[0, 1, 2];', }, + { + code: 'Array?.(0, 1, 2);', + errors: [ + { + messageId, + type: AST_NODE_TYPES.CallExpression, + }, + ], + output: '[0, 1, 2];', + }, + { + code: ` +/* a */ /* b */ Array /* c */ /* d */ /* e */ /* f */?.( + 0, + 1, + 2, +); /* g */ /* h */ + `, + errors: [ + { + messageId, + type: AST_NODE_TYPES.CallExpression, + }, + ], + output: ` +/* a */ /* b */ [ + 0, + 1, + 2, +]; /* g */ /* h */ + `, + }, { code: ` new Array(0, 1, 2);